protected function ModuleBuilderComponentFormBase::elementCompound in Module Builder 7.2
Set form element properties specific to compound component properties.
Parameters
&$element: The form element for the component property.
FormStateInterface $form_state: The form state.
$property_info: The info array for the component property.
$form_default_value: The default value for the form element.
Return value
string The handling type to be applied to this element's value on submit.
File
- includes/
module_builder.form.inc, line 393
Class
- ModuleBuilderComponentFormBase
- Backport of ComponentFormBase from 8.x-3.x version.
Code
protected function elementCompound(&$element, FormStateInterface $form_state, $property_info, $form_default_value) {
// A compound property shows a fieldset element, for which we recurse and
// show another component.
// D7: use fieldset instead of details element.
$element['#type'] = 'fieldset';
$element['#collapsed'] = FALSE;
// Figure out how many items to show.
// If we're reloading the form in response to the 'add more' button, then
// form storage dictates the item count.
// If there's nothing set in form storage yet, it's the first time we're
// here and the number of items in the entity tells us how many items to
// show in the form.
// Finally, if that's empty, then show no items, just a button to add one.
$item_count = static::getCompoundPropertyItemCount($form_state, $element['#mb_value_address']);
if (is_null($item_count)) {
$item_count = count($form_default_value);
static::setCompoundPropertyItemCount($form_state, $element['#mb_value_address'], $item_count);
}
if (empty($item_count)) {
$item_count = 0;
static::setCompoundPropertyItemCount($form_state, $element['#mb_value_address'], $item_count);
}
// Property cardinality overrides anything else.
if (isset($property_info['cardinality'])) {
$item_count = min($item_count, $property_info['cardinality']);
if ($item_count == $property_info['cardinality']) {
// We're at the maximum item count.
$add_more = FALSE;
}
else {
// We're not yet at the cardinality: we can add more.
$add_more = TRUE;
}
}
else {
// Unlimited cardinality: can always add more.
$add_more = TRUE;
}
// Set up a wrapper for AJAX.
$wrapper_id = Html::getUniqueId(implode('-', $element['#mb_value_address']) . '-add-more-wrapper');
// TODO - use '#type' => 'container',?
$element['#prefix'] = '<div id="' . $wrapper_id . '">';
$element['#suffix'] = '</div>';
// Show the items in a table. This is single-column, with all child
// properties in the one cell, but we just want the striping for visual
// clarity.
// D7: this won't work, but theming a table inside a form in D7 is just too
// much faff. TODO: add borders or something?
$element['table'] = array(
'#type' => 'table',
);
// The address in the properties array to find this component's properties
// list.
$component_properties_address = $element['#mb_property_address'];
$component_properties_address[] = 'properties';
$component_value_address = $element['#mb_value_address'];
$component_value_address[] = 'properties';
$property_form_value_address = $element['#parents'];
for ($delta = 0; $delta < $item_count; $delta++) {
$row = [];
$delta_value_address = $component_value_address;
$delta_value_address[] = $delta;
$delta_form_value_address = $property_form_value_address;
$delta_form_value_address[] = $delta;
// Put all the properties into a single cell so it's a 1-column table.
// TODO: WTF NO STRIPING IN SEVEN THEME???
$delta_component_element = $this
->getCompomentElement($form_state, $component_properties_address, $delta_value_address, $delta_form_value_address, []);
$row['row'] = $delta_component_element;
$element['table'][$delta] = $row;
}
if ($add_more) {
// Show a button to add items, if they can be added.
$button_text = $item_count == 0 ? t('Add a @label item', [
'@label' => strtolower($property_info['label']),
]) : t('Add another @label item', [
'@label' => strtolower($property_info['label']),
]);
$element['actions']['add'] = array(
'#type' => 'submit',
// This allows FormAPI to figure out which button is the triggering
// element. The name must be unique across all buttons in the form,
// otherwise, the first matching name will be taken by FormAPI as being
// the button that was clicked, with unexpected results.
// See \Drupal\Core\Form\FormBuilder::elementTriggeredScriptedSubmission().
'#name' => implode(':', $element['#mb_value_address']) . '_add_more',
'#value' => $button_text,
'#limit_validation_errors' => [],
'#submit' => [
'mb_addItemSubmit',
],
'#ajax' => array(
'callback' => 'mb_itemButtonAjax',
'wrapper' => $wrapper_id,
'effect' => 'fade',
),
);
}
if ($item_count > 0) {
$element['actions']['remove'] = [
'#type' => 'submit',
'#name' => implode(':', $element['#mb_value_address']) . '_remove_item',
'#value' => t('Remove last item'),
'#limit_validation_errors' => [],
'#submit' => [
'mb_removeItemSubmit',
],
'#ajax' => array(
'callback' => 'mb_itemButtonAjax',
'wrapper' => $wrapper_id,
'effect' => 'fade',
),
];
}
return 'compound';
}