Problem/Motivation

Default yml build by ui for custom composite with multiple cardinality displays wrong. This appears to be in saving the yaml from the UI as manually adding the correct yaml renders as expected.

Steps to reproduce

Create a custom composite with multiple cardinality using the web-ui and setting the wrapper-type to fieldset (on the advanced tab), it generates the following yaml and renders as a container with a hanging label:

streaming_video_information:
  '#type': custom_composite
  '#title': 'Streaming Video Information'
  '#required': true
  '#multiple__header': false
  '#multiple__min_items': 1
  '#multiple__sorting': false
  '#multiple__add': false
  '#multiple__add_more_input': false
  '#multiple__add_more_button_label': 'Add additional video'
  '#multiple__add_more_input_label': ''
  '#element':
    title:
      '#type': textfield
      '#required': true
      '#title': 'Complete Title of Film'
    year:
      '#type': textfield
      '#required': true
      '#title': 'Year of Film Release'

which renders html as

<div id="streaming_video_information_table">
<div id="edit-streaming-video-information" class="js-webform-type-webform-custom-composite webform-type-webform-custom-composite js-form-item form-item js-form-type-webform-custom-composite form-type-webform-custom-composite js-form-item-streaming-video-information form-item-streaming-video-information">
<label class="js-form-required form-required">Streaming Video Information</label>
          <div class="webform-multiple-table webform-multiple-table-responsive">
<div class="tableresponsive-toggle-columns"><button type="button" class="link tableresponsive-toggle" title="Show table cells that were hidden to make the table fit within a small screen." style="display: none;">Hide lower priority columns</button></div><table data-drupal-selector="edit-streaming-video-information-items" id="edit-streaming-video-information-items" class="responsive-enabled table" data-striping="1" data-once="tableresponsive">
      <thead>
      <tr>
                            <th colspan="2"><span class="visually-hidden">Streaming Video Information</span></th>
              </tr>
    </thead>  
      <tbody>
...
Manual Fix

Manually modify the yaml to add the `'#wrapper-type': fieldset` and the item displays as expected.

streaming_video_information:
  '#type': custom_composite
  '#title': 'Streaming Video Information'
  '#required': true
  '#multiple__header': false
  '#multiple__min_items': 1
  '#multiple__sorting': false
  '#multiple__add': false
  '#multiple__add_more_input': false
  '#multiple__add_more_button_label': 'Add additional video'
  '#multiple__add_more_input_label': ''
  '#wrapper_type': fieldset
  '#element':
    title:
      '#type': textfield
      '#required': true
      '#title': 'Complete Title of Film'
    year:
      '#type': textfield
      '#required': true
      '#title': 'Year of Film Release'

which creates the proper html:

<div id="streaming_video_information_table">

<fieldset class="fieldgroup form-composite required js-webform-type-webform-custom-composite webform-type-webform-custom-composite js-form-item form-item js-form-wrapper form-wrapper" data-drupal-selector="edit-streaming-video-information" data-msg-required="Streaming Video Information field is required." id="edit-streaming-video-information">
      <legend>
    <span class="h2">Streaming Video Information</span>
  </legend>
  <div class="fieldset-wrapper">
                <div class="webform-multiple-table webform-multiple-table-responsive">
<div class="tableresponsive-toggle-columns"><button type="button" class="link tableresponsive-toggle" title="Show table cells that were hidden to make the table fit within a small screen." style="display: none;">Hide lower priority columns</button></div><table data-drupal-selector="edit-streaming-video-information-items" id="edit-streaming-video-information-items" class="responsive-enabled table" data-striping="1" data-once="tableresponsive">
      <thead>
      <tr>
                            <th colspan="2"><span class="visually-hidden">Streaming Video Information</span></th>
              </tr>
    </thead>
  
      <tbody>
...

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Issue fork webform-3601072

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

kwfinken created an issue. See original summary.

sriram s made their first commit to this issue’s fork.

sriram_s’s picture

Status: Active » Needs review

The render side of WebformCustomComposite is the culprit here. prepareElementPreRenderCallbacks() only sets the fieldset wrapper inside an if (isset($element['#wrapper_type'])) guard. But fieldset is the default wrapper type, so when you leave it as fieldset the property equals its default and gets stripped on save. The element comes back without #wrapper_type, the guard is skipped, and you get a bare div with the hanging label.

WebformCompositeFormElementTrait already handles this correctly everywhere else with $element['#wrapper_type'] ?? 'fieldset'. MR !906 just brings the custom composite in line with that. So the lean YAML isn't the bug to chase, honouring the default at render time is.

Test-wise, WebformCompositeCustomTest was actually asserting the buggy output (a plain on the wrapper-less basic composite), so I updated those lines to expect the fieldset + legend. Fails before, passes after.

Ignore the red pipeline, it's the fork runner (there's a banner on the MR saying as much). The full Composite group passes locally with and without the patch, and phpcs/phpstan come back clean.

liam morland’s picture

Version: 6.3.0-rc1 » 6.3.x-dev