1

Is it possible to attach an #ajax callback to a field when the form is being regenerated from a previous ajax event (like a submit button)?


What I tried

Adding the #ajax callback to the field when the form is reloading does not seems to trigger anything:

// Adding the ajax event to the field.
$form['my_field']['#ajax'] = array(
  'wrapper' => 'module_form',
  'callback' => 'module_form_ajax_callback',
);

The Drupal.settings array is not updated after the end of the ajax process. Seems like I'm trying to do something the Form API isn't able to do out of the box... Here's the result of the first ajax request: result of the first ajax request You can see there's still only the submit button in the form attached to an ajax event.

Update

I spotted the issue, it was somewhere else. My form is a multi-steps form, when a step is submitted, I rebuild the form with the previous steps and add the next one.

For the previous steps, I render them based on data available from $form_state['complete form'], the render array here is actually storing a lot more data than the one I had set in the first place, which was causing conflicts.

4
  • In which hook are you modifying the $form variable in your first block of code?
    – Beebee
    Commented Dec 11, 2014 at 10:24
  • In the initial form function, which is used to regenerate the form each time an #ajax event is triggered. Commented Dec 11, 2014 at 10:31
  • That's correct. What's in your callback? module_form_ajax_callback
    – Beebee
    Commented Dec 11, 2014 at 11:38
  • Only a return $form;, but I think I spotted the issue, it was somewhere else. My form is a multi-steps form, when the first step is submitted, I rebuild the form with with the first step and the new one. For the 1st step, I render it based on data available into $form_state['complete form'], the render array is actually different from the one I set in the first place, which creates problems. I need to make sure of that, if that's the issue, I'll write an answer and edit the question to make things more clear. Commented Dec 11, 2014 at 13:20

2 Answers 2

0

#attached Will not be processed properly on elements that was loaded with AJAX. Maybe it could, but it never worked for me. on the other hand, using #ajax worked for me without a fault. what I would try (obviously a guess because you didn't provide full SSCCE) would be:

$field['#ajax'] => array(
  'wrapper' => 'module_form',
  'callback' => 'module_form_ajax_callback',
  'event' => 'change',
);

If this element is created with an AJAX call from another element, it's AJAX will work.

3
  • That's what I tried in the first place but it didn't work :( I'll update my question (didn't know about the SSCCE, interesting!) Commented Dec 11, 2014 at 9:02
  • @thedotwriter Yea, SSCCE is only set of guidelines, bu it is very helpful set of guidelines. And see my reply on chat - I have this working, more layers of AJAX than you have, and I haven't hit that problems... I'm willing to try to play with your code, let's talk on chat (but prepare sscce first, anyway :) )
    – Mołot
    Commented Dec 11, 2014 at 9:11
  • My experience was different. I went to a very extreme ends with loading CSS/JS through Ajax. Even drupal_add_css-added CSS got transmitted during the Ajax call.
    – AKS
    Commented Dec 11, 2014 at 18:37
0

When rebuilding previous steps, I used data available from $form_state['complete form']. To be sure the #ajax is taken into account, I had to strip some values from the render array which were causing conflicts on the form generation.

Once I had included previous steps into $form, here's what I did to attach ajax to all the fields of those steps (because that's what I initial wanted to do):

/**
 * Remove data causing the ajax event to break.
 */

// Remove all "radio" fields stored into the "radios" field (may be useful for "checkboxes" field too).
foreach ($form[$field_name] as $key => $value) {
  if (strpos($key, '#') === false) {
    unset($form[$field_name][$key]);
  }
}

// Values removed based on tests (were causing weird behavior or breaking template).
unset($form[$field_name]['#defaults_loaded']);
unset($form[$field_name]['#theme_wrappers']);
unset($form[$field_name]['#ajax_processed']);
unset($form[$field_name]['#value']);

// Add the ajax callback.
$form[$field_name]['#ajax'] = array(
  'wrapper' => 'module_form',
  'callback' => 'module_form_ajax_callback',
);

The best thing to do would be not to use $form_state['complete form'] at all. But the module was already too big for such refactoring. So here you go :).

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.