Getting Views Bulk Operations working with Draggable Views.
Background
In Drupal 6, Views Bulk Operations and Draggable Views defined views style plugins in order to deliver their respective functionalities. While this is great it meant you could only have one or the other, not both.
Then Views 3 came along with support for views as forms. This is the functionality you see in Drupal Commerce that allows the cart page to be generated using views.
Drupal 7
In order to take advantage of this new functionality, Views Bulk Operations in Drupal 7 was rewritten as a field handler with form support instead of a style plugin. Similarly the new 7.x-2.x branch of Draggable Views is also a rewrite to utilise this functionality.
So this now means you can combine both Draggable functionality with Views Bulk Operations functionality in the one view right?
Unfortunately if you define multiple Bulk Operations in your view, Views Bulk Operations will remove the default Save button added by views. This button is needed by Draggable Views to save the new order. But this is Drupal, so all is not lost - you can add the Save button back with a custom module and some form alter hooks.
Writing the custom module
First of all we need to target the correct form, so grab the form id of the view you're trying to add the save button back to. If you don't know how to do this either inspect the dom and find the form tag or just implement hook_form_alter and output the $form_id parameter till you find the right one.
In this case we'll call our module mymodule and our form id will be views_form_myview_page. In case you didn't guess the format of the form id's generated by views follow a views_form_VIEWID_DISPLAYID patterm. So start with an implementation of hook_form_FORM_ID_alter
<span style="color: #000000"><span style="color: #0000BB"><?php<br></span><span style="color: #FF8000">/**<br> * Implements hook_form_FORM_ID_alter() for views_form_myview_page().<br> *<br> * Alter the form to add the 'save' button back in. This button is removed by <br> * views_bulk_operations - rendering draggableviews non-functional.<br> *<br> * @see views_bulk_operations_form<br> */<br></span><span style="color: #007700">function </span><span style="color: #0000BB">mymodule_form_views_form_myview_page_alter</span><span style="color: #007700">(&</span><span style="color: #0000BB">$form</span><span style="color: #007700">, </span><span style="color: #0000BB">$form_state</span><span style="color: #007700">) {<br> </span><span style="color: #FF8000">// Repair the save button removed by views_bulk_operations.<br> // Here we make sure that draggableviews is operating on the form.<br> </span><span style="color: #007700">if (isset(</span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'draggableviews'</span><span style="color: #007700">]) && !empty(</span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'draggableviews'</span><span style="color: #007700">]) &&<br> </span><span style="color: #FF8000">// And confirm the button is missing.<br> </span><span style="color: #007700">!isset(</span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'actions'</span><span style="color: #007700">][</span><span style="color: #DD0000">'submit'</span><span style="color: #007700">])) {<br> </span><span style="color: #FF8000">// Then we make sure the user has the correct permissions.<br> </span><span style="color: #007700">if (!</span><span style="color: #0000BB">user_access</span><span style="color: #007700">(</span><span style="color: #DD0000">'access draggableviews'</span><span style="color: #007700">)) {<br> </span><span style="color: #FF8000">// No need to fix save button.<br> </span><span style="color: #007700">return;<br> }<br> </span><span style="color: #FF8000">// Now we retrieve the Draggable Views options - Draggable Views allows you to<br> // override the caption on the 'Save' button as well as allow ajax submission.<br> </span><span style="color: #0000BB">$options </span><span style="color: #007700">= </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'view'</span><span style="color: #007700">][</span><span style="color: #DD0000">'#value'</span><span style="color: #007700">]-></span><span style="color: #0000BB">field</span><span style="color: #007700">[</span><span style="color: #DD0000">'draggableviews'</span><span style="color: #007700">]-></span><span style="color: #0000BB">options</span><span style="color: #007700">[</span><span style="color: #DD0000">'draggableviews'</span><span style="color: #007700">];<br> </span><span style="color: #FF8000">// Add back the save button.<br> </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'actions'</span><span style="color: #007700">][</span><span style="color: #DD0000">'submit'</span><span style="color: #007700">] = array(<br> </span><span style="color: #FF8000">// Use the label provided by Draggable Views.<br> </span><span style="color: #DD0000">'#value' </span><span style="color: #007700">=> </span><span style="color: #0000BB">t</span><span style="color: #007700">(</span><span style="color: #0000BB">$options</span><span style="color: #007700">[</span><span style="color: #DD0000">'save_button_label'</span><span style="color: #007700">]),<br> </span><span style="color: #DD0000">'#type' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'submit'</span><span style="color: #007700">,<br> </span><span style="color: #FF8000">// Attach a button level submit handler so Views Bulk Operations submit handlers<br> // don't fire when the 'Save' button is clicked.<br> </span><span style="color: #DD0000">'#submit' </span><span style="color: #007700">=> array(</span><span style="color: #DD0000">'draggableviews_views_form_submit'</span><span style="color: #007700">),<br> </span><span style="color: #FF8000">// Ensure that form level validation does not occur when the 'Save' button is clicked<br> // (otherwise Views Bulk Operations won't be happy that you've not selected any rows<br> // or an operation).<br> </span><span style="color: #DD0000">'#validate' </span><span style="color: #007700">=> array(</span><span style="color: #DD0000">'mymodule_psuedo_validate'</span><span style="color: #007700">),<br> );<br><br> </span><span style="color: #FF8000">// Respect the original Draggable Views ajax configuration option<br> </span><span style="color: #007700">if (</span><span style="color: #0000BB">$options</span><span style="color: #007700">[</span><span style="color: #DD0000">'ajax'</span><span style="color: #007700">]) {<br> </span><span style="color: #0000BB">$form</span><span style="color: #007700">[</span><span style="color: #DD0000">'actions'</span><span style="color: #007700">][</span><span style="color: #DD0000">'submit'</span><span style="color: #007700">][</span><span style="color: #DD0000">'#ajax'</span><span style="color: #007700">] = array(<br> </span><span style="color: #DD0000">'callback' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'draggableviews_view_draggabletable_form_ajax'</span><span style="color: #007700">,<br> );<br> }<br> }<br>}<br></span><span style="color: #0000BB">?></span></span>
Now we've got our save button back - we just need to write the validation handler 'mymodule_psuedo_validate'.
As you can guess from the name, it doesn't do anything other than prevent the save button firing the form level validation code (without this Views Bulk Operations will return validation errors regarding selection of rows and an operation).
<span style="color: #000000"><span style="color: #0000BB"><?php<br></span><span style="color: #FF8000">/**<br> * Psuedo validation handler<br> *<br> * @param array $form<br> * the form<br> * @param array $form_state<br> * the form state<br> *<br> * @see views_bulk_operations_form_validate()<br> */<br></span><span style="color: #007700">function </span><span style="color: #0000BB">mymodule_psuedo_validate</span><span style="color: #007700">(</span><span style="color: #0000BB">$form</span><span style="color: #007700">, &</span><span style="color: #0000BB">$form_state</span><span style="color: #007700">) {<br> </span><span style="color: #FF8000">// We deliberately do nothing here, if this validation handler isn't attached<br> // to our 're-added' save button then views_bulk_operations_form_validate is<br> // called and validation fails.<br></span><span style="color: #007700">}<br></span><span style="color: #0000BB">?></span></span>
Wrapping up
And that's basically it with this you can create a flexible administration view for your content that rolls both ordering and common administrative tasks into a single form.
Thanks to the maintainers of Views Bulk Operations and Draggable Views for their work on these modules.
Category: Drupal Planet