Getting Views Bulk Operations working with Draggable Views.

Wed 29th Feb 2012 -- Lee Rowlands


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

* Implements hook_form_FORM_ID_alter() for views_form_myview_page().
* Alter the form to add the 'save' button back in. This button is removed by
* views_bulk_operations - rendering draggableviews non-functional.
* @see views_bulk_operations_form
function mymodule_form_views_form_myview_page_alter(&$form, $form_state) {
// Repair the save button removed by views_bulk_operations.
  // Here we make sure that draggableviews is operating on the form.
if (isset($form['draggableviews']) && !empty($form['draggableviews']) &&
// And confirm the button is missing.
!isset($form['actions']['submit'])) {
// Then we make sure the user has the correct permissions.
if (!user_access('access draggableviews')) {
// No need to fix save button.
// Now we retrieve the Draggable Views options - Draggable Views allows you to
    // override the caption on the 'Save' button as well as allow ajax submission.
$options = $form['view']['#value']->field['draggableviews']->options['draggableviews'];
// Add back the save button.
$form['actions']['submit'] = array(
// Use the label provided by Draggable Views.
'#value' => t($options['save_button_label']),
'#type' => 'submit',
// Attach a button level submit handler so Views Bulk Operations submit handlers
      // don't fire when the 'Save' button is clicked.
'#submit' => array('draggableviews_views_form_submit'),
// Ensure that form level validation does not occur when the 'Save' button is clicked
      // (otherwise Views Bulk Operations won't be happy that you've not selected any rows
      // or an operation).
'#validate' => array('mymodule_psuedo_validate'),

// Respect the original Draggable Views ajax configuration option
if ($options['ajax']) {
$form['actions']['submit']['#ajax'] = array(
'callback' => 'draggableviews_view_draggabletable_form_ajax',

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).

* Psuedo validation handler
* @param array $form
*   the form
* @param array $form_state
*   the form state
* @see views_bulk_operations_form_validate()
function mymodule_psuedo_validate($form, &$form_state) {
// We deliberately do nothing here, if this validation handler isn't attached
  // to our 're-added' save button then views_bulk_operations_form_validate is
  // called and validation fails.

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.