0

I have a form and I want to do the following

  1. Click a link to popup a modal JqueryUI Dialog window
  2. Load into this window, via AJAX, a Form
  3. Submit the form via AJAX
  4. Upon successful submission, Close the popup automatically

I have stages 1 and 2 working fine, but step 3 is causing me problems. If I create a form page which uses more or less the same code (different wrapper and function names but identical code) AJAX form submitting works just fine, so the problem seems to be that somehow the form HTML within the JQuery Dialog is not being processed to use AJAX.

Here is my code;

My Menu Item;

  // test ajax callback
  $items['teststuff/dialog-load/ajax'] = array(
'title' => t('Load Dialog AJAX callback'),
'type' => MENU_CALLBACK,
'page callback' => 'teststuff_dialog_load',
'access arguments' => array('access content'),
);

Form functions in my 'teststuff' module;

function teststuff_dialog_load () {
  // Get the form
  $form = drupal_get_form('teststuff_meal_entry3_form');

  return drupal_json_output(drupal_render($form));
}

function teststuff_meal_entry3_form($form, &$form_state) {
  $form = array();

  $form['date'] = array(
    '#type' => 'date_popup', // types 'date_popup', 'date_text' and 'date_timezone' are also supported. See .inc file.
    '#title' => 'Date and Time Eaten',
    '#default_value' => date("Y-m-d H:i:s"), 
    '#date_format' => "Y-m-d H:i", // YY-MM-DD HH:MM
    '#date_label_position' => 'within', // See other available attributes and what they do in date_api_elements.inc
    '#date_increment' => 15, // Optional, used by the date_select and date_popup elements to increment minutes and seconds.
    '#date_year_range' => '-1:+1', // Optional, used to set the year range (back 3 years and forward 3 years is the default).
    '#required' => TRUE,
  );

  $form['meal_name'] = array(
    '#type' => 'textfield',
    '#title' => t('Meal Name'),
    '#size' => 60,
    '#maxlength' => 100,
    '#description' => t('Enter a name for this meal'),
    '#required' => TRUE,
  );  

  $form['actions'] = array('#type' => 'actions');
  $form['actions']['submit'] = array( '#type' => 'submit', '#value' => t('Create Meal'));

 $form['actions']['submit']['#ajax'] = array(
       'callback' => 'teststuff_meal_entry3_form_ajax_callback',
       'wrapper' => 'teststuff-dialog-inner',
       'method' => 'replace',
       'effect' => 'fade',
     );

  return $form;  
}

function teststuff_meal_entry3_form_submit($form, &$form_state) {
  // Validation is all good, so note the success
  $form_state['teststuff_meal_entry3_form_success'] = 1;
}


function teststuff_meal_entry3_form_ajax_callback(&$form, &$form_state) {
  if (!empty($form_state['teststuff_meal_entry3_form_success'])) {
    $confirmation = array(
      '#type' => 'markup',
      '#markup' => '

The form was successfully submitted

',); return $confirmation; } else { return $form; } }

My JQuery

// Force Entry form to become a dialog and load info dynamically
// via AJAX
// Item has class 'myajax-popup'
(function($){
  Drupal.behaviors.make_dialog_myajax_popup = {
    attach: function (context, settings) {

      function ajaxCompleted (data) {
        // Parse Json
        // Add some stuff to your DOM.
        console.log(data);
        $('#teststuff-dialog-inner').html(data);
        Drupal.attachBehaviors($('#teststuff-dialog-inner'));
      }

      $('.myajax-popup').addClass("processed").click(function() {
        // Create a dialog
        var myDialog;

        // See if element already exists
        if ($("#teststuff-dialog-outer").length > 0) {
          // Dialog element exists, don't create
          myDialog = $("#teststuff-dialog-outer");
        }
        else {
          myDialog = $('');
          myDialog.appendTo('body');
        }

        $('#teststuff-dialog-inner').html('Initial content');


        myDialog.dialog({
            modal: true,
            width: 600,
            height: 'auto',
            hide: 'slide',
            title: "Title" });      

        // Fire ajax to fill the dialog
        $.ajax({
          type: 'POST',
          url: '/teststuff/dialog-load/ajax',
          dataType: 'json',
          success: ajaxCompleted,
        });

        return false;
      });
    }
  };
})(jQuery);

And my link to open the popup;

<a href="#" class="mydialog-load">Popup LOAD into dialog</a>

Upon clicking Submit, The browser simply redirects to;

/teststuff/dialog-load/ajax (the callback link)

and the output on that page is the JSON

"\u003Cform action=\u0022/teststuff/dialog-load/ajax\u0022 ... snipped..."

Is anyone able to tell me what I am doing wrong and why my ajax submit (that works if the form is a full page form) is failing to do what I want it to do.

It's as if my call to Drupal.attachBehaviors() is not firing properly and not adding in the relevant ajax code. Although one of my own widget replacement behaviours is definitely running on the loaded form content.

I have managed to get the Dialog API module working. I also have the code working fine if I create a block on the page, initially hidden via CSS, but then turn it into a JQuery UI Dialog.

I just want this more dynamic behaviour to load in the form dynamically and prefer to avoid using extra modules if I can do so, especially when I am 66% of the way there! I'd also like to understand why I have the problem I have, rather than just taking the easier ways out.

1 Answer 1

2

0 down vote

I finally got the answer to the problem! After days of struggling with it, I got a reply in the following post from Drupal expert, Jaypan: http://drupal.org/node/1517414.

I tweaked his answer a bit and set the settings after rendering the form like this:

$html = drupal_render(drupal_get_form('myform'));

$javascript = drupal_add_js(NULL, NULL); $settings = FALSE;

if(isset($javascript['settings'])) { $settings = 'jQuery.extend(Drupal.settings, '. drupal_json_encode(call_user_func_array('array_merge_recursive', $javascript['settings']['data'])) .');'; }

$html .= $settings; print $html;

I hope this will fix your problem as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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