diff --git a/core/modules/field_ui/js/field_ui.js b/core/modules/field_ui/js/field_ui.js index 6113dec7b1b2b9e7e49c6582543f9814e136684b..41de06be3a0ffdb3f9a48d13ad18b11613528a1a 100644 --- a/core/modules/field_ui/js/field_ui.js +++ b/core/modules/field_ui/js/field_ui.js @@ -159,6 +159,15 @@ rowHandler.region = region; } + // Handle parent change. + const parent = rowHandler.getParent(); + if (parent !== rowHandler.parent) { + // Let the row handler deal with the parent change. + $.extend(refreshRows, rowHandler.parentChange(parent)); + // Update the row parent. + rowHandler.parent = parent; + } + // Fields inside `.tabledrag-hide` are typically hidden. They can be // visible when "Show row weights" are enabled. If their value is changed // while visible, the row should be marked as changed, but they should not @@ -205,6 +214,19 @@ // Ajax-update the rows. Drupal.fieldUIOverview.AJAXRefreshRows(refreshRows); } + + const parentRow = $row.prevAll('tr.field-group').get(0); + const parent = parentRow?.id ?? ''; + + // Handle parent change when row is dropped. + if (parent !== rowHandler.parent) { + // Let the row handler deal with the parent change. + const refreshRows = rowHandler.parentChange(parent); + // Update the row parent. + rowHandler.parent = parent; + // Ajax-update the rows. + Drupal.fieldUIOverview.AJAXRefreshRows(refreshRows); + } } }, @@ -355,10 +377,12 @@ this.row = row; this.name = data.name; this.region = data.region; + this.parent = data.parent; this.tableDrag = data.tableDrag; this.defaultPlugin = data.defaultPlugin; this.$pluginSelect = $(row).find('.field-plugin-type'); this.$regionSelect = $(row).find('select.field-region'); + this.$parentSelect = $(row).find('select.field-parent'); // Attach change listeners to select and input elements in the row. $(row).find('select, input').on('change', Drupal.fieldUIOverview.onChange); @@ -379,6 +403,19 @@ } }, + /** + * Returns the parent corresponding to the current form values of the row. + * + * @return {string} + * The parent field name or empty string if there is no parent. + */ + getParent() { + if (this.$parentSelect.length) { + return this.$parentSelect[0].value; + } + return ''; + }, + /** * Reacts to a row being changed regions. * @@ -432,6 +469,36 @@ return refreshRows; }, + + /** + * Reacts to a row being changed parent. + * + * This function is called when the row's parent is changed, as a result of + * user input in one of the form elements watched by the + * {@link Drupal.fieldUIOverview.onChange} change listener. + * + * @param {string} parent + * The name of the new parent for the row. + * + * @return {object} + * A hash object indicating which rows should be Ajax-updated as a result + * of the change, in the format expected by + * {@link Drupal.fieldUIOverview.AJAXRefreshRows}. + */ + parentChange(parent) { + // Replace dashes with underscores. + parent = parent.replace(/-/g, '_'); + + if (this.$parentSelect.length) { + // Set the parent of the select list. + this.$parentSelect[0].value = parent; + } + + const refreshRows = {}; + refreshRows[this.name] = this.$parentSelect.get(0); + + return refreshRows; + }, }; /** diff --git a/core/modules/field_ui/src/Element/FieldUiTable.php b/core/modules/field_ui/src/Element/FieldUiTable.php index d830d77566819a73aed23e9684199b470180526f..bd00bd7160aa58c3e88916b64e7b6be6f1c85cfe 100644 --- a/core/modules/field_ui/src/Element/FieldUiTable.php +++ b/core/modules/field_ui/src/Element/FieldUiTable.php @@ -99,6 +99,7 @@ public static function tablePreRender($elements) { 'rowHandler' => $row['#row_type'], 'name' => $name, 'region' => $region_name, + 'parent' => $parent, ]; $js_settings[$id] = $row['#js_settings']; }