function drupal_attach_tabledrag in Drupal 9
Same name and namespace in other branches
- 8 core/includes/common.inc \drupal_attach_tabledrag()
Assists in attaching the tableDrag JavaScript behavior to a themed table.
Draggable tables should be used wherever an outline or list of sortable items needs to be arranged by an end-user. Draggable tables are very flexible and can manipulate the value of form elements placed within individual columns.
To set up a table to use drag and drop in place of weight select-lists or in place of a form that contains parent relationships, the form must be themed into a table. The table must have an ID attribute set and it may be set as follows:
$table = array(
'#type' => 'table',
'#header' => $header,
'#rows' => $rows,
'#attributes' => array(
'id' => 'my-module-table',
),
);
return \Drupal::service('renderer')
->render($table);
In the theme function for the form, a special class must be added to each form element within the same column, "grouping" them together.
In a situation where a single weight column is being sorted in the table, the classes could be added like this (in the theme function):
$form['my_elements'][$delta]['weight']['#attributes']['class'] = array(
'my-elements-weight',
);
Each row of the table must also have a class of "draggable" in order to enable the drag handles:
$row = array(...);
$rows[] = array(
'data' => $row,
'class' => array('draggable'),
);
When tree relationships are present, the two additional classes 'tabledrag-leaf' and 'tabledrag-root' can be used to refine the behavior:
- Rows with the 'tabledrag-leaf' class cannot have child rows.
- Rows with the 'tabledrag-root' class cannot be nested under a parent row.
Calling drupal_attach_tabledrag() would then be written as such:
drupal_attach_tabledrag('my-module-table', array(
'action' => 'order',
'relationship' => 'sibling',
'group' => 'my-elements-weight',
);
In a more complex case where there are several groups in one column (such as the block regions on the admin/structure/block page), a separate subgroup class must also be added to differentiate the groups.
$form['my_elements'][$region][$delta]['weight']['#attributes']['class'] = array(
'my-elements-weight',
'my-elements-weight-' . $region,
);
The 'group' option is still 'my-element-weight', and the additional 'subgroup' option will be passed in as 'my-elements-weight-' . $region. This also means that you'll need to call drupal_attach_tabledrag() once for every region added.
foreach ($regions as $region) {
drupal_attach_tabledrag('my-module-table', array(
'action' => 'order',
'relationship' => 'sibling',
'group' => 'my-elements-weight',
'subgroup' => 'my-elements-weight-' . $region,
));
}
In a situation where tree relationships are present, adding multiple subgroups is not necessary, because the table will contain indentations that provide enough information about the sibling and parent relationships. See MenuForm::BuildOverviewForm for an example creating a table containing parent relationships.
Parameters
$element: A form element to attach the tableDrag behavior to.
array $options: These options are used to generate JavaScript settings necessary to configure the tableDrag behavior appropriately for this particular table. An associative array containing the following keys:
- 'table_id': String containing the target table's id attribute. If the table does not have an id, one will need to be set, such as <table id="my-module-table">.
- 'action': String describing the action to be done on the form item.
Either 'match' 'depth', or 'order':
- 'match' is typically used for parent relationships.
- 'order' is typically used to set weights on other form elements with the same group.
- 'depth' updates the target element with the current indentation.
- 'relationship': String describing where the "action" option
should be performed. Either 'parent', 'sibling', 'group', or 'self':
- 'parent' will only look for fields up the tree.
- 'sibling' will look for fields in the same group in rows above and below it.
- 'self' affects the dragged row itself.
- 'group' affects the dragged row, plus any children below it (the entire dragged group).
- 'group': A class name applied on all related form elements for this action.
- 'subgroup': (optional) If the group has several subgroups within it, this string should contain the class name identifying fields in the same subgroup.
- 'source': (optional) If the $action is 'match', this string should contain the classname identifying what field will be used as the source value when matching the value in $subgroup.
- 'hidden': (optional) The column containing the field elements may be entirely hidden from view dynamically when the JavaScript is loaded. Set to FALSE if the column should not be hidden.
- 'limit': (optional) Limit the maximum amount of parenting in this table.
See also
MenuForm::BuildOverviewForm()
3 calls to drupal_attach_tabledrag()
- FieldUiTable::tablePreRender in core/
modules/ field_ui/ src/ Element/ FieldUiTable.php - Performs pre-render tasks on field_ui_table elements.
- Table::preRenderTable in core/
lib/ Drupal/ Core/ Render/ Element/ Table.php - #pre_render callback to transform children of an element of #type 'table'.
- template_preprocess_views_ui_rearrange_filter_form in core/
modules/ views_ui/ views_ui.theme.inc - Prepares variables for Views UI rearrange filter form templates.
File
- core/
includes/ common.inc, line 343 - Common functions that many Drupal modules will need to reference.
Code
function drupal_attach_tabledrag(&$element, array $options) {
// Add default values to elements.
$options = $options + [
'subgroup' => NULL,
'source' => NULL,
'hidden' => TRUE,
'limit' => 0,
];
$group = $options['group'];
$tabledrag_id =& drupal_static(__FUNCTION__);
$tabledrag_id = !isset($tabledrag_id) ? 0 : $tabledrag_id + 1;
// If a subgroup or source isn't set, assume it is the same as the group.
$target = isset($options['subgroup']) ? $options['subgroup'] : $group;
$source = isset($options['source']) ? $options['source'] : $target;
$element['#attached']['drupalSettings']['tableDrag'][$options['table_id']][$group][$tabledrag_id] = [
'target' => $target,
'source' => $source,
'relationship' => $options['relationship'],
'action' => $options['action'],
'hidden' => $options['hidden'],
'limit' => $options['limit'],
];
$element['#attached']['library'][] = 'core/drupal.tabledrag';
}