Drupal : Creating Form with Drag and Drop Ordering
Published on Thursday, May 29, 2014
So you want to create a form with drag and drop ordering in Drupal 7? Here are 3 simple steps to create a form with drag and drop ordering:
1. Implement hook_menu, to register the URL of the form
function module_name_menu() { $items = array(); $items['admin/config/content/module_name/manage'] = array( 'title' => 'Recent News: List Links', 'page callback' => 'drupal_get_form', 'page arguments' => array('module_name_manage'), 'access arguments' => array('access administration pages'), ); }
We will use the following function to render the form:
function module_name_manage() { $db_result = db_query( "select id,title position from recent_news order by position"); // create array and add one element called data $rows= array(); $form['#tree'] = TRUE; $max = 60; foreach($db_result as $row){ $title = $row->title; if(strlen($title)>$max) $title = substr($title,0,$max).' ...'; $form['slides'][$row->id]['id'] = array( '#type' => 'hidden', '#default_value' => $row->id, ); // Textfield to hold content id. $form['slides'][$row->id]['title'] = array( '#type' => 'item', '#title' => $title ); // This field is invisible, but contains sort info (weights). $form['slides'][$row->id]['weight'] = array( '#type' => 'weight', '#title' => t('Weight'), '#title_display' => 'invisible', '#default_value' => $row->position, ); } $form['submit'] = array('#type' => 'submit', '#value' => t('Save changes')); return $form; }
2. implement hook_theme, to register theme implementation of form with drag and drop support
function module_name_theme($existing, $type, $theme, $path) { return array( 'module_name_manage' => array( 'render element' => 'form', ), ); }
And here is the callback function which will render the form with drag and drop capabilities
function theme_module_name_manage($variables) { $form = $variables['form']; $rows = array(); foreach (element_children($form['slides']) as $nid) { $form['slides'][$nid]['weight']['#attributes']['class'] = array('slides-order-weight'); $rows[] = array( 'data' => array( array('class' => array('slide-cross')), drupal_render($form['slides'][$nid]['title']), drupal_render($form['slides'][$nid]['weight']), ), 'class' => array('draggable'), ); } $header = array('',t('title'),t('position')); $output = drupal_render($form['note']); $output .= theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'slides-order'))); $output .= drupal_render_children($form); drupal_add_tabledrag('slides-order', 'order', 'sibling', 'slides-order-weight'); return $output; }
3. Implement hook_submit, to handle form submit and save the ordering
function module_name_manage_submit($form, &$form_state) { $slides = array(); foreach ($form_state['values']['slides'] as $slide) { $slides[] = array( 'id' => $slide['id'], 'weight' => $slide['weight'], ); } if (!empty($slides)) { usort($slides, '_module_name_arraysort'); } $position = 1; foreach($slides as $slide){ $id = $slide['id']; $sql = "UPDATE recent_news SET position={$position} WHERE id = {$id}"; db_query($sql); $position++; } drupal_set_message(t('Ordering have been saved.')); } // Custom array sort function by weight. function _module_name_arraysort($a, $b) { if (isset($a['weight']) && isset($b['weight'])) { return $a['weight'] < $b['weight'] ? -1 : 1; } return 0; }
The code is quite long but you can just copy and paste then modify it if necessary. This tutorial is based on Ki Kim’s post on http://www.urbaninsight.com/2012/09/11/creating-table-with-draggable-weights-in-drupal-7