Drupal: Working with Ctools Modal Popup

I’ve been creating a lot of Ctools Popups lately. It has become my preferred way of creating form-based modal popups in Drupal. This post will describe how to use Ctools popups to display forms.

Defining a Custom Style

The first step I take before creating a ctools popup is define the custom style – a custom style is not needed in order to display the popup, but I often need to change the default dimensions of the popup.

$custom_style = array(
  'node-edit-display-modal-dialog-style' => array(
    'modalSize' => array(
      'type' => 'fixed',
      'width' => 400,
       height' => 430,
    ),
    'animation' => 'fadeIn',
  ),
);
drupal_add_js($custom_style, 'setting');

Creating a Link

Now, I have to create a link that includes the ctools-use-modal class (and the custom style that I just created). The following is a link that I created in recently developed module.

ctools_include('ajax');
ctools_include('modal');
ctools_modal_add_js();
 
$form['node_edit_display_add_action']['node_node_edit_display_add_role_exceptions'] = array(
  '#markup' => l(t('Role Exceptions'), "node-edit-display/nojs/exceptions/add/$key/$field_name/$roleId/$content_type", array('html' => TRUE, 'attributes' => array('class' => "ctools-use-modal ctools-modal-node-edit-display-modal-dialog-style"))),
);

Menu Hook

At this point, the link that I created above does not exist, so I have to define it in hook_menu.

function node_edit_display_menu() {
  $items = array();$items['node-edit-display/%ctools_js/exceptions'] = array(
    'page callback' => 'node_edit_display_ctools_modal_exceptions_popup',
    'page arguments' => array(1),
    'access callback' => TRUE,
    'file' => 'inc/node_edit_display.exceptions.inc',
  );return $items;
}

When the link is clicked, it will call the function node_edit_display_ctools_modal_exceptions_popup. This function will define what I want to display in the popup.

function node_edit_display_ctools_modal_exceptions_popup($js = FALSE) {
 ctools_include('modal');
 ctools_include('ajax');
 
// Create array $form_state.
 $title = ucfirst(arg(3));
 $form_state = array(
   'title' => t($title .' Action Role Exceptions'),
   'ajax'  => TRUE,
 );
 //add the action type, roleId, formId to the form state
 $form_state['build_info']['args'] = array(arg(3));
 $form_state['build_info']['args'][] = arg(5);
 $form_state['build_info']['args'][] = arg(6);
 $form_state['build_info']['args'][] = arg(7);
 $output = ctools_modal_form_wrapper('node_edit_display_ctools_modal_exceptions_form', $form_state);
 // Actions after form submit.
 if (!empty($form_state['executed'])) {
   $output = array();
   $value = _node_edit_display_get_role_exception_ids($form_state['values']['node_edit_display_action_role_exceptions']);
   _node_edit_display_set_role_exception_ids($form_state, $value);
   $id = 'node-edit-display-'.arg(3).'-exceptions-'. arg(5). '-'. arg(4);
   $input = '<div id="node-edit-display-'.arg(3).'-exceptions-body-'. arg(4) . '">';
   $input .= '<input type="hidden" value="'. $value . '" name="node_edit_display_fields_wrapper[';
   $input .= arg(4).'][node_edit_display_'. arg(3) .'_action][node_edit_display_role_exception_values]" />';
   $input .= '</div>';
   $output[] = ajax_command_replace('#'.$id, $input);
   $output[] = ctools_modal_command_dismiss();
}
if (!$output) {
    $output = array();
    $output[] = ctools_modal_command_dismiss();
}
 print ajax_render($output);
}

I passed arguments to the popup in the link:

l(t('Role Exceptions'), "node-edit-display/nojs/exceptions/add/$key/$field_name/$roleId/$content_type");

I created a form_state array and then filled the build info with arguments that I passed.

/* $key */
$form_state['build_info']['args'] = array(arg(3));
/* $field_name */
$form_state['build_info']['args'][] = arg(5);
/* $roleId */
$form_state['build_info']['args'][] = arg(6);
/* $content_type */
$form_state['build_info']['args'][] = arg(7);

Using the build info array is not necessary to create the ctools popup, but since I pass the form_state as an argument to the ctools_modal_form_wrapper, it’s a handy way to store the values:

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

Submit and Cancel Buttons

The modal popup will display two buttons (submit and cancel). To check whether the submit button was clicked:

if (!empty($form_state['executed'])) {
 
}

If want the modal popup to close when the submit button is clicked:

if (!empty($form_state['executed'])) {
  //do some processing
  $output[] = ctools_modal_command_dismiss()
}

To cancel/close the modal popup when the cancel button is clicked:

if (!$output) {
  $output = array();
  $output[] = ctools_modal_command_dismiss();
}

Using Ctools Modal PopUp with a Node Edit Form

So far, we have used Ctools Modal PopUp to create custom forms, but we can use the same techniques to create a Node Edit form. First we create a link that will pass the node id.

$form['node_edit_form'] = array(
  '#markup' => l(t('Edit'), "node-edit-popup/nojs/$node_id ", array('html' => TRUE, 'attributes' => array('class' => "ctools-use-modal ctools-modal-node-edit-display-modal-dialog-style"))),
);

Then we create a menu item that passes the node id to a function:

$items['node-edit-popup/%ctools_js/%'] = array(
  'page callback' => 'my_module_node_edit_form_popup',
  'page arguments' => array(1, 2),
  'access callback' => TRUE,
);

We create the function that takes the node id.

function my_module_node_edit_form_popup($js = FALSE, $nid) {
  ctools_include('modal');
  ctools_include('ajax');
  // Create array $form_state.
  $form_state = array(
    'title' => t(Node Edit'),
    'ajax'  => TRUE,
  );
  $form_state['build_info']['args'] = array($nid);
  $output = ctools_modal_form_wrapper('my_module_edit_form', $form_state);
}

In the edit form, we use the node_form function.

function my_module_edit_form($form, &$form_state) {
  module_load_include('inc', 'node', 'node.pages');
  $nid = $form_state['build_info']['args'][0];
  if ($nid == NULL) {
    // build add form
    $node = new StdClass();
    $node->type = 'my_content_type';
    $node->language = LANGUAGE_NONE;
    node_object_prepare($node);
    $form_id = $node->type . '_node_form';
    $form = node_form($form, $form_state, $node);
  } else {
    // build edit form
    $node = node_load($nid);
    $form = node_form($form, $form_state, $node);
  }
  return $form;
}

That’s it. Creating modal forms with Drupal’s Ctools Popup is fairly straightforward. Enjoy.

Be Sociable, Share!

Checkout My New Site - T-shirts For Geeks