Skip to content

Instantly share code, notes, and snippets.

@opi
Last active May 11, 2017 14:17
Show Gist options
  • Save opi/bc892fe62974d67d9af1b2d57ba0d6c6 to your computer and use it in GitHub Desktop.
Save opi/bc892fe62974d67d9af1b2d57ba0d6c6 to your computer and use it in GitHub Desktop.
Drupal multiple field : Add new item on top of the list
<?php
// Insert new item on top of the list.
// Display file input first for better UI (https://lut.im/0AkZwIQOUa/dtzEPerqgp3hQ3hk.png)
// In a .module
/**
* Implements hook_field_attach_form().
* Inspired from add_to_top contrib module
*/
function MYMODULE_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode = NULL) {
if (isset($form['#entity_type']) && isset($form['#bundle'])) {
// Get all field instances on this bundle.
$field_info_instances = field_info_instances($form['#entity_type'], $form['#bundle']);
// Iterate over each instance.
foreach ($field_info_instances as $field_name => $field_info_instance) {
if ($field_name == 'field_my_multiple_field' && isset($form[$field_name])) {
$langcode = $form[$field_name]['#language'];
// Make a reference to the position in the array.
$field = &$form[$field_name][$langcode];
// First get the delta of the new (last) item.
$max = max(array_keys($field));
// Set the _weight to -100 so its always at the top.
$field[$max]['_weight']['#default_value'] = -100;
$field[$max]['#weight'] = -100;
}
}
}
}
// In the theme's template.php file
/**
* Override theme_file_widget_multiple().
*/
function MYTHEME_file_widget_multiple($variables) {
$element = $variables['element'];
if ($element['#field_name'] != 'field_my_multiple_field') {
// Default theme function
return theme_file_widget_multiple($variables);
}
else {
// Note: Same as theme_file_widget_multiple() default function except that
// the items table is render at the end
// Special ID and classes for draggable tables.
$weight_class = $element['#id'] . '-weight';
$table_id = $element['#id'] . '-table';
// Build up a table of applicable fields.
$headers = array();
$headers[] = t('File information');
if ($element['#display_field']) {
$headers[] = array(
'data' => t('Display'),
'class' => array('checkbox'),
);
}
$headers[] = t('Weight');
$headers[] = t('Operations');
// Get our list of widgets in order (needed when the form comes back after
// preview or failed validation).
$widgets = array();
foreach (element_children($element) as $key) {
$widgets[] = &$element[$key];
}
usort($widgets, '_field_sort_items_value_helper');
$rows = array();
foreach ($widgets as $key => &$widget) {
// Save the uploading row for last.
if ($widget['#file'] == FALSE) {
$widget['#title'] = $element['#file_upload_title'];
$widget['#description'] = $element['#file_upload_description'];
continue;
}
// Delay rendering of the buttons, so that they can be rendered later in the
// "operations" column.
$operations_elements = array();
foreach (element_children($widget) as $sub_key) {
if (isset($widget[$sub_key]['#type']) && $widget[$sub_key]['#type'] == 'submit') {
hide($widget[$sub_key]);
$operations_elements[] = &$widget[$sub_key];
}
}
// Delay rendering of the "Display" option and the weight selector, so that
// each can be rendered later in its own column.
if ($element['#display_field']) {
hide($widget['display']);
}
hide($widget['_weight']);
// Render everything else together in a column, without the normal wrappers.
$widget['#theme_wrappers'] = array();
$information = drupal_render($widget);
// Render the previously hidden elements, using render() instead of
// drupal_render(), to undo the earlier hide().
$operations = '';
foreach ($operations_elements as $operation_element) {
$operations .= render($operation_element);
}
$display = '';
if ($element['#display_field']) {
unset($widget['display']['#title']);
$display = array(
'data' => render($widget['display']),
'class' => array('checkbox'),
);
}
$widget['_weight']['#attributes']['class'] = array($weight_class);
$weight = render($widget['_weight']);
// Arrange the row with all of the rendered columns.
$row = array();
$row[] = $information;
if ($element['#display_field']) {
$row[] = $display;
}
$row[] = $weight;
$row[] = $operations;
$rows[] = array(
'data' => $row,
'class' => isset($widget['#attributes']['class']) ? array_merge($widget['#attributes']['class'], array('draggable')) : array('draggable'),
);
}
drupal_add_tabledrag($table_id, 'order', 'sibling', $weight_class);
$output = '';
// Magic happens here.
// File input element first
$output .= drupal_render_children($element);
// Then items table
$output .= empty($rows) ? '' : theme('table', array('header' => $headers, 'rows' => $rows, 'attributes' => array('id' => $table_id)));
return $output;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment