7

I need to do some extra things after Drupal ajax is done inserting some stuff into the DOM. With jQuery this was brain-dead simple, but I can't for the life of me figure out how to do it in Drupal 7 :s

Do I add something to my ajaxified link? I read something about attaching a behavior...confusion is setting in...

1
  • 3
    1. What is triggering the AJAX call? 2. Behaviors are the right approach. 3. They are not really hard ;) Jan 5, 2012 at 0:56

7 Answers 7

6

I ended up adding some additions commands to the page that is being returned by the ajax handler like this:

$commands = array();
$commands[] = ajax_command_invoke(NULL, 'grid_content_loading', array('argument1', 'argument2'));
$commands[] = ajax_command_append('#grid-content-target', $html);
$commands[] = ajax_command_invoke(NULL, 'grid_content_loaded', array('argument1', 'argument2'));
$page = array('#type' => 'ajax', '#commands' => $commands);
ajax_deliver($page);

And on the client side I created 2 javascript funtions through jQuery:

(function($) {
$.fn.grid_content_loading = function($argument1, $argument2) {
   ...
};

$.fn.grid_content_loaded = function($argument1, $argument2) {
   ...
};
})(jQuery);
2
  • 1
    Have you looked at Drupal.Behaviors, like amateur barista suggested? Jan 5, 2012 at 8:08
  • For example, if you want to update a hidden field with id "block", you can use: $commands[] = ajax_command_invoke('#block', 'val', array($value)); Apr 26, 2013 at 14:33
3

In my project, I had already written well-defined JavaScript code that updated the page stats after an AJAX call.

Since I wanted to reuse the functions without going to the extent of "extending jQuery", I ended up with the following solution, using an existing jQuery function, instead of defining a new one. This was inspired by what the 'flags' module does -- it simply triggers an event, and allows many Javascript event listeners to act in response, as opposed to having just a single hard-coded, custom jQuery plugin/extension as in the solution explored in the previous answers.

In a Drupal Module:

// in_some_ajax_function()

$commands[] = ajax_command_invoke('html', 'trigger', array('MY_EVENT'));

In Javascript:

// Added an event binding to my $(document).ready();

$(document).ready(function(){

  $(document).bind('MY_EVENT', function() {
    alert('MY_EVENT');
  });

});

I had to note that the first parameter for ajax_command_invoke is NEVER any native JavaScript objects, so the following never works, because it translates into a 'document' (element) selector:

// This tries to select $('document')
// ... which is nothing, since there are no 'document' elements.

$commands[] = ajax_command_invoke('document', 'trigger', array('MY_EVENT'));

Curiously, binding on $(document) and triggering on $('html') are compatible. I suppose you can get very creative, and bind/trigger on more specific, deeper-level elements. If you can think of a scenario where doing so makes more sense than a top-level event trigger, please comment!

1
  • Thanks! Also you can add a second argument, next to "MY_EVENT" in this answer, to pass it to the function executed by your event in your JS code. For passing multiple arguments or objects you could use json_encode. Your JS event should receive 2 arguments, your first argument is the event itself and the second argument is your JSON_ENCODED thing. PHP: ajax_command_invoke('html', 'trigger',['agregar_qtip',json_encode(['#edit-linea-0-id-producto','No existe'])]) JS: $(document).bind('MY_EVENT', function (event, args) { }); Hope that helps! May 20, 2015 at 0:57
3

Code sample:

$commands = array();
$commands[] = array(
    'command' => 'your_js_callback', // the name of your javascript callback
    'value1'  => 'My first value',
    'value2'  => 'My second value',
);
ajax_render($commands);

JS Code:

(function($, Drupal) {
    Drupal.ajax.prototype.commands.your_js_callback = function(ajax, response, status) {
        alert(response.value1);
        alert(response.value2);
    }
})(jQuery, Drupal);
2

I think that the best option is use the jQuery ajaxComplete function:

(function($){ 
   $(document).ajaxComplete(function(e, xhr, settings)
   {
     alert(settings.url);
   });
}(jQuery));

And if you want use the function for specific ajax function you can use the identified settings.url for your field and change that to:

(function($) {
    $(document).ajaxComplete(function(e, xhr, settings){ 
    if (settings.url == "the path from step 1") {
        // Code to populate your fields here
    }
 });
}(jQuery));

This worked for me for Drupal 7 and 8.

0

Quick hack solution: Place an image inside the loaded content and give it the onload="[javascript function]()" attribute. Not sure this is actually what you're looking for... Or if this is easier than the correct way... But maybe better than nothing?

0

I've posted an answer to this question on so

https://stackoverflow.com/a/19404566/894487

I'm not sure of the real differences between extending Drupal.ajax.prototype.commands or $.fn

I imagine the former would be more efficient as their is no dom traversal required to hit your function. Not sure if that is important.

0

I wrote a tutorial on how to do this in Drupal 7: https://www.jaypan.com/tutorial/calling-function-after-ajax-event-drupal-7

Your Answer

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

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