1

I have form in modal window with two selects. Second field hidden and appears with ajax after first field selected.

  1. If i click Submit when first select is not defined and second is hidden - modal window dismisses;
  2. If i click Submit when first select defined and second is visible (i.e. form was refreshed with ajax), instead of modal dismiss i see raw output in browser:

[{"command":"settings","settings":{"basePath":"/","pathPrefix":"","ajaxPageState":{"theme":"opie","theme_token":"5OSo2MbF_rbvJauMUEumH0Mm-gFubWX6Ai-FqvwO9lo"},"fancybox":{"options":{"padding":0,"scrolling":"visible","nextClick":1},"helpers":{"overlay":{"fixed":0}},"selectors":["a[rel=\u0022fancybox\u0022]","a.fancybox","img[rel=\u0022fancybox\u0022]",".gallery-frame a"]}},"merge":true},{"command":"modal_dismiss"}]

Can you help me to understand why is that?

Main code:

function modal_callback($mode = NULL) {
    if ($mode == 'ajax') {
        ctools_include('ajax'); ctools_include('modal');
        $form_state = array('ajax' => TRUE, 'title' => 'Title');

        $output = ctools_modal_form_wrapper('stage_form', $form_state);
        if (!empty($form_state['ajax_commands'])) $output = $form_state['ajax_commands'];

        print ajax_render($output); drupal_exit();
    }
    else return drupal_get_form('stage_form');
}

function stage_form($form, $form_state) {
    $form['#prefix'] = '<div id="form-wrapper">';
    $form['#suffix'] = '</div>';   
    $form['start'] = array(
        '#type' => 'select',
        '#options' => array('1'=>'1', '2'=>'2'),
        '#ajax' => array(
            'callback' => 'form_refresh',
            'wrapper' => 'form-wrapper',
        ),
    );
    if (!empty($form_state['values']['start'])) {
        $form['stop'] = array(
            '#type' => 'select',
            '#options' => array('3'=>'3', '4'=>'4'),
        );
    }
    $form['submit'] = array(
        '#type' => 'submit',
        '#value' => 'Submit',
    );
}

function form_refresh($form, $form_state) {
    return $form;
}

function stage_form_submit($form, &$form_state) {
    $form_state['ajax_commands'][] = ctools_modal_command_dismiss();
}
0

I'm not familiar with that ctools command, however try:

$commands = [];

$commands[] = ajax_command_name();

return ['#type' => 'ajax', '#commands' => $commands];

What you ultimately want is for Drupal to receive and render the commands array which should trigger the dismiss and not print the commands to the screen.

(On phone, sorry for formatting)

  • ajax_render($output) delivers dismiss command in first case, why it does not in second? – ntym Mar 14 '16 at 12:20
  • Did you try render(ajax_render($output))? I forget where I ran into this, but I did not have a lot of luck with the print/drupal_exit in AJAX callbacks, particularly with forms, and let Drupal handle that by returning the callback response. – Kevin Mar 14 '16 at 13:06
  • Ok, will check that. Btw, just now discovered, form_set_error in second case causes raw output in browser too. – ntym Mar 14 '16 at 13:33
  • Yeah, my general practice with ajax callbacks in forms is to just return the command array - however it might be different with ctools exclusive commands - I either use the ones in core, or my own callbacks. – Kevin Mar 14 '16 at 13:48
0

I found the sollution. Problem was in my misunderstanding. Upper code supposes ctools_modal_command_dismiss(); would be handled by modal_callback(), but it's wrong way. Dismiss command demands own callback, handling all form ajax in modal window. Next code properly works with validation messages and dynamic form elements.

function test_menu() {
    $items['testpage'] = array(
        'page callback' => 'test_page',
        'access callback' => TRUE,
        'type' => MENU_CALLBACK,
    );
    $items['test'] = array(
        'page callback' => 'test_callback',
        'access callback' => TRUE,
        'type' => MENU_CALLBACK,
    );
    return $items;
}


function test_page() {
    // Load the modal library and add the modal javascript.
    ctools_include('modal');
    ctools_modal_add_js();
    return test_make_link('Magical modal');
}

function test_form($form, $form_state) {
    $form['#prefix'] = '<div id="test_frm">';
    $form['#suffix'] = '</div>';
    $form['name'] = array(
        '#type' => 'select',
        '#title' => t('Name'),
        '#options' => array(1 => 1, 2 => 222, 99999999 => '99999999'),
        '#ajax' => array(
            'callback' => 'test_form_ajax_handler'
        ),
    );
    $form['name1'] = array(
        '#type' => 'textfield',
        '#title' => t('Name'),
        '#value' => isset($form_state['values']['name']) ? $form_state['values']['name'] : '',
        '#maxlength' => '128',
    );

    $form['submit'] = array(
        '#type' => 'submit',
        '#value' => 'Submit',
        '#ajax' => array(
            'callback' => 'test_form_ajax_handler'
        ),
    );
    return $form;
}

function test_form_submit(&$form, &$form_state) {
    $form_state['rebuild'] = TRUE;
}

function test_form_validate(&$form, &$form_state) {
    if (strlen($form_state['values']['name1'])<5) form_set_error('name', '!!!!!!!!!!!!!!!!!!!!!!');
}

function test_form_ajax_handler(&$form, &$form_state) {
    ctools_include('ajax'); ctools_include('modal');


    if ($form_state['executed']) {
        $link = test_make_link($form_state['values']['name']);
        $commands[] = ctools_modal_command_dismiss();
        $commands[] = ajax_command_replace('#magical-modal-link', $link);
    } elseif ($form_state['submitted']) {
        $commands[] = ajax_command_remove('#messages-wrap');
        $commands[] = ajax_command_before('#test_frm', '<div id="messages-wrap">' . theme('status_messages') . '</div>');
        $commands[] = ajax_command_replace('#test_frm', drupal_render($form));
    } else {
        $commands[] = ajax_command_remove('#messages-wrap');
        $commands[] = ajax_command_replace('#test_frm', drupal_render($form));
    }
    return array('#type' => 'ajax', '#commands' => $commands);

}

function test_callback($ajax) {
    if ($ajax) {
        ctools_include('ajax');
        ctools_include('modal');

        $form_state = array('ajax' => TRUE, 'title' => t('MyModule Modal Form'));

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

        if (!empty($form_state['ajax_commands'])) {$output = $form_state['ajax_commands'];}
        print ajax_render($output);  drupal_exit();
    } else {
        return drupal_get_form('test_form');
    }
}
function test_make_link($link_text = '') {
    // Set a default value if no text in supplied.
    if (empty($link_text)) {
        $link_text = 'Magical Modal';
    }

    return '<div id="magical-modal-link">' . l($link_text, 'test/nojs', array('attributes' => array('class' => 'ctools-use-modal'))) . '</div>';
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.