1

I'm facing a problem with Ajax enabled forms, so this is the scenario. I have 2 blocks, the first one has some buttons and the other one has a form ,constructed using the Form API.

When I click any of the buttons in the first block and AJAX Request is sent to the server, then in my callback function it replaces the second's block form data with new values, for doing this I call the drupal_get_form function, so the code for the callback is more or less like this:

$form = drupal_get_form('panorama_info_form');
print render($form);

And the elements of the form have the following style:

//Text field for title
$form['panorama_titulo'] = array(
        '#type' => 'textfield',
        '#title' => t('Nombre del panorama'),
        '#default_value' => $panorama['titulo'],
        '#description' => t('Nombre del panorama'),
        '#size' => 40,
        '#maxlenght' => 120,
        '#required' => TRUE,
        '#prefix' => '<div id="panorama_titulo_div">',
        '#suffix' => '</div>',
        '#ajax' => array(
          'callback' => 'panorama_info_form_callback',
          'wrapper' => 'panorama_titulo_div',
          'method'  => 'replace',
          'effect' => 'fade',),);

Now, in my jQuery Http 200 success function I replace the old form with the response data like this:

function reload_element(data){
    $("#panorama-info-form").replaceWith(data);

}

where data is the rendered form.

This works, and I can see my form with the new default values that I declared, however after the form is replaced, ajax is no longer triggered by events. What I mean is that before I replaced the form with jQuery, it used to work, the value was sent to the server and the callback function declared for the textfield was in fact getting called. However after the replacement, no more ajax request... Why is this happening??? I guess that's because there's some kind of script that uses the form's element's classes to attach functions dynamically to it... Maybe that could be one reason. How could I fix this??? Thanks a lot.

1

You don't post the code performing the actual AJAX request, so I have to assume it's directly calling an URL returning just the rendered version of the textfield wrapper with id "panorama_titulo_div".

Since this is sort of side-stepping Drupal's own AJAX functionality (which operates on a per-form basis, initiated by the "#ajax" key being present on certain elements), you'll need to perform some steps manually.

First you need to tell elements in the form that they are about to be removed using Drupal.detachBehaviors($('#panorama_titulo_div').get(0), Drupal.settings, 'unload');

Then you replace the form like you already do.

Finally, you need to re-attach all the JavaScript behaviors since any script operating on the elements in the replaced form won't have any references to the new elements.

Drupal.attachBehaviors($('#panorama_titulo_div').get(0)); This is where Drupal would normally pass the settings received together with other commands returned from an AJAX operation. We don't have that here, and it's not that important since we're not adding/removing elements or otherwise alter the DOM structure and won't introduce any new scrips. Just to be sure every behaviors works, Drupal calls Drupal.attachBehaviors() again with the entire form as the context argument. You may want to do that too if you notice some things aren't working. It's a safe operation since all behaviors are required to keep track of whether they're already attached or not (often done using jQuery's .once() method.

  • Very well written answer, friend. Welcome to DSO. – stefgosselin Jul 10 '13 at 2:58
  • Thanks! I tried to be as clear as possible, but it's difficult without full code samples. – TwoD Aug 18 '13 at 12:43

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.