Essantially what I'm trying to do is to open a modal dialog (containing another form) during an AJAX form-callback. So far I know that I can bring up modal dialogs by using

- a link (class: "ctools-use-modal")
- a form that holds a button and a hidden url element

In my case I need to be able to open a form (in a modal dialog) dependant on user input e.g the result of a select-list-element.

I see basically two ways of accomplishing this:

1. Put an AJAX-callback to the select-list that changes the hidden url-field -> open the modal with a button. This worked BUT when I close the modal dialog the select list's ajax callback won't get triggered anymore (so it only works the first time).

2. Leave the button out and open the modal at the select lists's AJAX-callback directly. This also works BUT the modal-forms submit callback gets ignored.

Does anyone have an idea to solve this? Here's my example code (version 2):

/**
 * Implementation of hook_menu()
 */
function ajax_madness_menu() {
    $items = array();   
    $items['ajax-madness/dependant-modal'] = array(
        'title' => t("dependant modal"),
        'page callback' => 'ajax_madness_dependant_modal_page',     
        'access callback' => true,      
        'type' => MENU_CALLBACK,        
    );          
    $items['ajax-madness/dependant-modal/form/%'] = array(
        'title' => t("dependant modal"),
        'page callback' => 'drupal_get_form',
        'page arguments' => array("ajax_madness_dependant_modal_form",3),       
        'access callback' => true,      
        'type' => MENU_CALLBACK,        
    );  
    return $items;      
}

/**
 * Page with modal form selector
 */
function ajax_madness_dependant_modal_page() {
    ctools_include('ajax');
    ctools_include('modal');
    ctools_modal_add_js();  
    $build = array();
    $build["dependant_select_form"]["#markup"] = render(drupal_get_form("ajax_madnesss_select_modal_form"));    
    return $build;  
}

/**
 * Select the modal form
 */ 
function ajax_madnesss_select_modal_form($form,&$form_state) {
    $form["select"] = array(
        "#type" => "select",
        "#title" => t("Select modal form"),
        "#options" => array(
            1 => t("Modal form @number",array("@number" => 1)),
            2 => t("Modal form @number",array("@number" => 2)),
            3 => t("Modal form @number",array("@number" => 3)),
        ),  
        "#ajax" => array(
            "callback" => "ajax_madnesss_select_modal_form_ajax",
        ),
    );      
    return $form;       
}

/**
 * Select the modal form ajax callback
 */ 
function ajax_madnesss_select_modal_form_ajax($form,&$form_state) {
    ctools_include('ajax');
    ctools_include('modal');                

    $new_form_state = form_state_defaults();
    $new_form_state["ajax"] = true;
    $new_form_state["title"] = drupal_get_title();  
    $new_form_state['build_info']['args'] = array($form_state["values"]["select"]); 

    $output = ctools_modal_form_wrapper("ajax_madness_dependant_modal_form", $new_form_state);  
    if(!empty($new_form_state['ajax_commands'])) {
        $output = $new_form_state['ajax_commands'];
    }           
    print ajax_render($output);
    drupal_exit();
}

/**
 * The form that should be displayed in the modal
 */ 
function ajax_madness_dependant_modal_form($form,&$form_state,$option) {        
    $form["text"] = array(
        "#type" => "textfield",
        "#default_value" => t("Congratulations! You selected modal with option nr. @option",array("@option" => $option)),
    );  

    $form["#submit"][] = "ajax_madness_dependant_modal_form_submit";

    $form["submit"] = array(
        "#type" => "submit",
        "#value" => t("Close the modal & submit"),  
    );  
    return $form;
}

/**
 * Form submit function (never gets called)
 */
function ajax_madness_dependant_modal_form_submit($form,&$form_state) {
    dpm("Got called");
    ctools_include('ajax');
    ctools_include('modal');    
    $form_state['ajax_commands'][] = ctools_modal_command_dismiss();
    $form_state['ajax_commands'][] = ctools_ajax_command_reload();
    drupal_set_message(t("Congratulations! You submitted the MADNESS!"));
}

Comments

daze20’s picture

Issue summary: View changes
tim.plunkett’s picture

Status: Active » Fixed

Please look at the ctools_ajax_sample module included in CTools. It has many diverse examples, which should cover your needs.
If it doesn't, you'll at least know more and be able to ask a more targeted question.

daze20’s picture

Status: Fixed » Needs review

Thanks for answering to my problem. I looked at the ctools_ajax_sample (along with many other modules that use the modal component) but couldn't find the same use case. The question target is simple: I want to open a modal dialog that contains a form BUT it should get triggerd by an ajax event (e.g. a select list). In use case terms:

- user selects a value from a select-list (triggers an AJAX callback)
- a modal dialog opens that contains another form
- this modal form "knows" what the user selected in the dropdown list

Now the way I did it kinda works: the modal form comes up and displays nicely BUT the submit trigger of that form is broken! So it must have something to do with the AJAX form wrappers (ctools_modal_form_wrapper). When I click the submit button, I see that a call to "system/ajax" is made with the right variables -> but nothing comes back (message length=0). As shown in my code sample, the submit function doesn't event get triggered.

lstirk’s picture

Hi did you ever find a solution to this? I have the same problem

damienmckenna’s picture

Version: 7.x-1.4 » 7.x-1.x-dev
Status: Needs review » Active
anpolimus’s picture

Have the same issue.
Modal content is not showing, when I'm trying to show it from ajax callack.
Here is my code:

function hnb_system_form_comment_form_alter(&$form, &$form_state, &$form_id) {
  dpm($form);
  ctools_include('modal');
  ctools_include('ajax');
  ctools_modal_add_js();
  $form['comment_body']['#after_build'][] = 'hnb_system_comments_form_theme';
  $form['actions']['submit2'] = array(
    '#type' => 'button',
    '#value' => 'modal_test',
    '#prefix' => '<div id="hnb_system_comment_form_wrapper_11">',
    '#suffix' => '</div>',
    '#ajax' => array(
      'callback' => '_hnb_system_comment_ajax',
      'wrapper' => 'hnb_system_comment_form_wrapper_11',
    )
  );
}

function _hnb_system_comment_ajax($ajax) {
  ctools_include('modal');
  ctools_include('ajax');
  //ctools_modal_add_js();
  $commands[]  = ctools_modal_command_display('test title', 'test');
  return array(
      '#type' => 'ajax',
      '#commands' => $commands,
  );
}

anpolimus’s picture

Assigned: Unassigned » anpolimus
Category: Support request » Bug report
anpolimus’s picture

anpolimus’s picture

Status: Active » Needs work
podarok’s picture

Status: Needs work » Needs review

Bot ping

dstorozhuk’s picture

Issue summary: View changes
dstorozhuk’s picture

Status: Needs review » Closed (won't fix)

Not an issue. Works perfect in both variants, reported by anpolimus and daze20.

Here is a fixes and updated code for daze20:

/**
 * Select the modal form ajax callback
 */
function ajax_madnesss_select_modal_form_ajax($form,&$form_state) {
  ctools_include('ajax');
  ctools_include('modal');

  $new_form_state = form_state_defaults();
  $new_form_state["ajax"] = true;
  $new_form_state["title"] = drupal_get_title();
  $new_form_state['build_info']['args'] = array($form_state["values"]["select"]);

  $output = ctools_modal_form_wrapper("ajax_madness_dependant_modal_form", $new_form_state);
  if(!empty($new_form_state['ajax_commands'])) {
    $output = $new_form_state['ajax_commands'];
  }
  print ajax_render($output);
  drupal_exit();
}

/**
 * The form that should be displayed in the modal
 */
function ajax_madness_dependant_modal_form($form, &$form_state, $option) {
  $form["text"] = array(
    "#type" => "textfield",
    "#default_value" => t("Congratulations! You selected modal with option nr. @option",array("@option" => $option)),
  );

  $form["#submit"][] = "ajax_madness_dependant_modal_form_submit";

  $form["submit"] = array(
    "#type" => "submit",
    '#ajax' => array(
      'callback' => 'ajax_madness_dependant_modal_form_ajax_submit'
    ),
    "#value" => t("Close the modal & submit"),
  );
  return $form;
}

function ajax_madness_dependant_modal_form_submit($form, &$form_state) {
  drupal_set_message(t("Congratulations! This get called too!"));
}

/**
 * Form submit function (never gets called)
 */
function ajax_madness_dependant_modal_form_ajax_submit($form, &$form_state) {

  ctools_include('ajax');
  ctools_include('modal');
  $commands[] = ctools_modal_command_dismiss();
  $commands[] = 'some another command to manipulate parent form';
  $commands[] = 'some another command to manipulate page after submit modal form';
  // Reload if need, but also can just rebuild part of content.
  $commands[] = ctools_ajax_command_reload();

  drupal_set_message(t("Congratulations! You submitted the MADNESS!"));

  return array(
    '#type'     => 'ajax',
    '#commands' => $commands,
  );
}

What was changed:
In ajax_madness_dependant_modal_form(), for submit button added ajax callback, which return ajax commands.

Actually, have no idea where did you (daze20) get that:

$form_state['ajax_commands'][] = ctools_modal_command_dismiss();
 $form_state['ajax_commands'][] = ctools_ajax_command_reload();

and why do you think this should works.

anpolimus’s picture

Thanks