Opening a ctools modal on form submit I have a custom profile form (part of a multi-step registration process) that requires a modal to be displayed once submitted. I am not clear on what the process is for this to happen, and the documentation i've seen isn't clear.

What I have tried (as seen below) is adding the submit action via a $form['#action'] which only returns the JS Object for the modal. Clearly, this isn't working. What should I do to render this modal when the form submits, while assuring the validation and submit calls fire?

The actual Ctools Modal logic is in its own modal, of which it generates on a hook_menu() call to the correct route.

function example_profile_update_form($form, $form_state) {
  $form = array();

  $form['item'] = array(
    "#type" =&gt; 'textfield',
  );

  $form['#validate'][] = "example_profile_update_validate";
  $form['#action'] = url("modal/updated/nojs"); //Implemented as a hook_menu() call in its own module
  $form['#submit'][] = "example_profile_update_submit";

  return $form;
}
Form API and Ajax frameworks work quite well together. 

In your submit button, that you want to trigger the popup, it should work as an Ajax element first. 

$form['submit'] = array(
  '#type' =&gt; 'submit',
  '#value' =&gt; 'Submit (and open popup)',
);


If you use submit and validate handlers as you have shown in your question, those submit and validate handlers will be executed at this point. If you want different submit/validate handlers, then you have to add them to the submit button itself. 

Now, add #ajax property to the element. 

$form['submit'] = array(
  '#type' =&gt; 'submit',
  '#value' =&gt; 'Submit (and open popup)',
  '#ajax' =&gt; array(
    'wrapper' =&gt; 'id_of_some_unique_element',
    'callback' =&gt; 'my_module_give_this_function_a_nice_name',  
  ),
);
ctools_include('modal');
ctools_modal_add_js();


We play a trick here. Typically, #ajax property is used to replace some parts of the form. That's why we use the wrapper to indicate the replacing element. This will not be used at all if you trigger the modal, but make sure you refer to a unique DIV. Better leave it empty.

The callback is what we need. This callback should be a PHP function name, that returns some or full $form first parameter, or, it can print some Ajax commands. Do not set $form_state['rebuild'] = TRUE in your #submit handler.

ctools_add_modal_js() adds the modal.js file because it's necessary to trigger the popup. 

function my_module_give_this_function_a_nice_name($form, &amp;$form_state) {
  // this function gets the $form_state after submitting the form. All values, including the submitted values preserved. 
}


Now, we need to print the modal contents. 

function my_module_give_this_function_a_nice_name($form, &amp;$form_state) {
  // this function gets the $form_state after submitting the form. All values, including the submitted values preserved. 
  ctools_include('modal');
  ctools_modal_add_js();
  $commands = array();
  $commands[] = ctools_modal_command_display('title', 'modal content goes here');
  // You can add extra modal using drupal_add_js/css. You can also have them `#attached` to a rendarable array that you are going to print. 
  print ajax_render($commands);
  exit;
}