Hi,

I have been struggling with this issue for over a week, and I was hoping I could get some advice. I have been successfully using the CTools Modal API with forms that I have created myself, and it is working great. Thanks for this awesome tool.

I have also been trying, however, to integrate modal windows with the Views Bulk Operations (VBO) form, and have kept running into roadblocks. The difficulty is that what I am trying to do is to reload the VBO form inside of the modal, passing it the $form_state and $plugin variables required by the function views_bulk_operations_form($form_state, $plugin), so that I can render the form as it would appear on the Configuration step of VBO (e.g., where one selects which taxonomy terms to assign to the selected nodes). I am not really understanding from the documentation how to pass the $form_state or the $form from an existing form into a CTools modal window and reload the new version of the form inside of it.

I've tried two different methods of manipulating the form through the form API to pass the form submit values to the Views Bulk Operations form, but neither seems to work.

The first method I tried was to create a hidden form field pointing to page I am calling back to render the modal output. This method is described in the Advanced Help as follows:

For submit buttons, however, the URL may be found a different, slightly more complex way. If you do not wish to simply submit the form to the modal, you can create a URL using hidden form fields. The ID of the item is taken and -url is appended to it to derive a class name. Then, all form elements that contain that class name are founded and their values put together to form a URL.

For example, let's say you have an 'add' button, and it has a select form item that tells your system what widget it is adding. If the id of the add button is edit-add, you would place a hidden input with the base of your URL in the form and give it a class of 'edit-add-url'. You would then add 'edit-add-url' as a class to the select widget allowing you to convert this value to the form without posting. If no URL is found, the action of the form will be used and the entire form posted to it.

Here is an example of the code I used for this method:

/**
 * Implements hook_menu().
 */
function mymodule_menu() {
  $items = array();
  $items['ctools-my-organizer/%ctools_js/add-to-sharepage/%'] = array(
    'title' => 'Add to Share Page',
    'access callback' => TRUE,
    'page callback' => 'mymodule_add_to_sharepage_modal',
    'page arguments' => array(1,3),
    'type' => MENU_CALLBACK,
  );
  return $items;
}
/**
 * Implements hook_form_alter().
 */
function mymodule_form_alter(&$form, &$form_state, $form_id) {
  if (strpos($form_id, 'views_bulk_operations_form__1') === 0) {
    global $base_url;
    if (isset($form['select'])) {
      // Include CTools files for modal dialog
      ctools_include('ajax'); // Module  include the dependence it needs for ajax.
      ctools_include('modal');
      ctools_modal_add_js();
      drupal_add_js(array(
        'my-modal-style' => array(
          'modalSize' => array(
            'type' => 'fixed',
            'width' => 350,
            'height' => 350,
          ),
        ),
      ), 'setting');
      $form['select']['mymodule_add_to_sharepage_action']['#attributes']['class'] = 'ctools-use-modal ctools-modal-my-modal-style';
      $form['select']['sharepage_hidden_input'] = array(
        '#type' => 'hidden',
        '#value' => 'ctools-my-organizer/nojs/add-to-sharepage',
        '#attributes' => array('class' => 'edit-mymodule-add-to-sharepage-action-url'),
      );
    }
  }
}
/**
 * Page callback for loading the Add to Sharepage form of Views Bulk Operations into a modal window.
 */
function mymodule_add_to_sharepage_modal($js = NULL, $args = array()) {
  if ($js) {
    ctools_include('ajax');
    ctools_include('modal');
    // Set up the $form_state from the $args somehow
    $output = ctools_modal_form_wrapper('views_bulk_operations_form__1', $form_state), // Not sure if this will even work, since the views_bulk_operations_form() function requires both $form_state and $plugin
    ctools_ajax_render($output);
  }
  else {
  // Render the form some non-modal way
  }
}

The other method I tried, per the comments in the issue Problem passing search values to modal form with CTools, was to post the form directly to the callback URL rather than using the hidden form field to pass the URL. I changed the hook_form_alter() function as follows:

      //$form['select']['mymodule_add_to_sharepage_action']['#attributes']['class'] = 'ctools-use-modal ctools-modal-my-modal-style';
      $form['select']['mymodule_add_to_sharepage_action']['#submit'] = array('mymodule_add_to_sharepage_modal');
      $form['#action'] = 'ctools-my-organizer/nojs/add-to-sharepage';
		  
      /*
      $form['select']['sharepage_hidden_input'] = array(
        '#type' => 'hidden',
        '#value' => 'ctools-my-organizer/nojs/add-to-sharepage',
        '#attributes' => array('class' => 'edit-mymodule-add-to-sharepage-action-url'),
      );
      */

In both cases I don't believe the existing $form or $form_state were being passed into the modal. It was difficult to tell, because my attempts to use the dpm(get_defined_vars()) function inside of the page callback for the modal window kept causing errors. Sometimes, however, when I refreshed the page I would see the Krumo information returned from the dpm() function on the parent page, and based on the line number it appeared to be a result of the dpm() function call in the modal page callback. In the cases where I could see the Krumo/dpm() information, the $form and $form_state did not seem to be coming through.

Is what I'm trying to do even possible? I've been having a difficult time understanding how to pass the data from an existing form into the CTools modal window, so I would HUGELY appreciate any help/advice anyone can give me. Also, if anyone has suggestions about how to print variables inside of the modal window, that would be a huge help, too.

Thanks!
Dan

Comments

danmuzyka’s picture

Oops, typo, one of my lines of code was actually:

  $output = ctools_modal_form_wrapper('views_bulk_operations_form__1', $form_state);

(Semi-colon not comma at the end.)

afreeman’s picture

I ran into a similar problem and came up with a solution. It isn't elegant but it works: change the form action before you trigger your modal.

My use case: I have a rather involved form that automates building email templates. The spec I'm working from calls for a preview button that loads a modal which displays the output of the template combined with some default values for the token substitutions. Like you I was initially confused when my modal triggered and no values from my form where present in $_POST.

I spent some time tinkering with the value-passing functionality you get when you declare a hidden URL and add classes to the form fields you want to pass data from, and that worked until (predictably) I needed to send the contents of a couple textareas. Then I took a closer look at this:

Like with all CTools' AJAX functionality, the href of the link will be the destination, with any appearance of /nojs/ converted to /ajax/. For submit buttons, however, the URL may be found a different, slightly more complex way. If you do not wish to simply submit the form to the modal, you can create a URL using hidden form fields. The ID of the item is taken and -url is appended to it to derive a class name. Then, all form elements that contain that class name are founded and their values put together to form a URL. For example, let's say you have an 'add' button, and it has a select form item that tells your system what widget it is adding. If the id of the add button is edit-add, you would place a hidden input with the base of your URL in the form and give it a class of 'edit-add-url'. You would then add 'edit-add-url' as a class to the select widget allowing you to convert this value to the form without posting. If no URL is found, the action of the form will be used and the entire form posted to it.

(emphasis mine).

This tells me that ctools modals will post the form, but only to the form action. So I whipped up a little jQuery to change the form action to URL of my modal menu callback when the preview button is moused over:

$(document).ready(function(){
  // Stash the original form action.
     $old_action = $('#node-form').attr('action');
  

  // Add mouseover function to swap form action
  $('#edit-template-wrapper-preview').mouseover(function(){
    $('#node-form').get(0).setAttribute('action', '/email_confirmation/preview_modal');
     $action = $('#node-form').attr('action');
      alert("action:" + $action); // Added for debugging purposes.
  });

  // Add mouseout function to swap form action back to the original value
  ...
});

Now, when I check $_POST in my modal callback function the entire contents of my form are available. Hope this helps, and if anyone has a better solution please post up!

1kenthomas’s picture

Project: Chaos Tool Suite (ctools) » Views Bulk Operations (VBO)
Version: 6.x-1.8 » 7.x-3.2
Component: Code » User interface
Issue tags: -

OK-- let's move this to D7 and change the project to VBO, which is what it's really targeted at, right?

The question is really: "Is there a way to get Views Bulk Operation to place field options in the main VBO exposed dropdown?"

That would be really cool / useful versus a new page. Heck, even a modal overlay #overlay= would be nice -- you could do that.

(See
http://drupal.stackexchange.com/questions/116300/is-there-a-way-to-get-v...)

(This is not client-critical to me ATM, but would be nice)

1kenthomas’s picture

Title: Ctools Modal + Views Bulk Operations? » Way to place field options in main dropdown, or nearby?

Delta title.