Main menu

Quick Guide to using drupal_add_tabledrag and enjoying jquery drag and drop loveliness

6 March 2009

We are finding that the feature exciting most end users in Drupal 6 is the lovely new jquery based drag and drop, as seen on the blocks and menu edit pages - we will be quite happy never have to explain the concept of "weights" again. The best news is that you can add this functionality to your own forms for free - and here is how.

Build and theme the form

We are assuming your vaguely familiar with the form API - you can brush up here http://api.drupal.org/api/file/developer/topics/forms_api.html - so we won't go into too much detail here. Essentially we need to create a form that will be themed into a table, each row in the table will need a form element capable of holding the "weight" or "order" value.

function example_form(&$form_state){

//fetch the data from the DB $result = db_query("SELECT id, value1, value2, weight FROM {foo} ORDER BY weight ASC");

//now create the weight form element. //NOTE how we add the id into the element key $form['rows'][$row->id]['weight-'.$row->id]=array( '#type'=>'textfield', '#size'=>5, '#default_value'=>$weight, //add a specific class in here - we need this later '#attributes' => array('class'=>'weight'), ); }

That should create a pretty basic and ugly form - we now need to theme this as a table

function theme_example_form($form){ //loop through each "row" in the table array foreach($form['rows'] as $id => $row){ //we are only interested in numeric keys if (intval($id)){ $this_row = $row['data']['#value'];

//Add the weight field to the row $this_row[] = drupal_render($form['rows'][$id]['weight-'.$sid]);

// Call add_tabledrag to add and setup the JS for us // The key thing here is the first param - the table ID // and the 4th param, the class of the form item which holds the weight drupal_add_tabledrag('example-table', 'order', 'sibling', 'weight');

return $output; }

Don't forget - we are in Drupal 6 land now so we need to register our theme function before it will take affect (how many times have I forgotten this already!)

Handle the submit

We should now have a working drag and drop enabled form themed as a table, we now need to handle the submit and store our new weight values.

function example_form_submit($form, &$form_state) { foreach($form_state['values'] as $key=>$data){ //we are only interested in weight elements if (substr($key,0,6)=='weight'){ //cunningly we have the DB id of the row in the element name $id = str_replace('weight-','',$key); db_query("UPDATE {foo} SET weight=%d WHERE id=%d",$data,$id); } } //optionally set the redirect value in form_submit ...}

Newbie here . Very helpful. One thing not real clear is where code for form submit function gets put, how it gets called , and where the the function is called that actually triggers rendering the form .

IE, i think you call in a template or module menu callback or somewhere that is page is generated. :

Great article! Very helpful... The tables are now appearing correctly for me, but the weight values are not being updated/saved at all... Nothing in the $form_state array reflects the appropriate weights on submit. Is there something missing somewhere?

Careful not to give your table the same id as you're form name (e.g. 'test-table' for table id, 'test_table' for form name) like I did. You'll end up wondering why you get obscure "this.table.tBodies is undefined" javascript errors.