12

I'm trying to figure out AJAX in Drupal 8.

I have a custom module that works, using AJAX to change the content of a div when a link is clicked.

The API says:

Many different events can trigger Ajax responses, including:

Clicking a button Pressing a key Moving the mouse

How do I trigger the same process that Drupal's AJAX does when a function is called from a JavaScript object's event firing instead?

JavaScript Object

function calledOnSomeEvent(e) {
  String data = e.target.data;
  // do something to call AJAX with the data
}

The AJAX backend works with this route:

myModule.routing.yml

myModule.myRoute:
  path: '/nojs/myFunction/{myParameter}'
  defaults:
    _controller: '\Drupal\myModule\MyController::myFunctionCallback'
    _title: 'myFunction'
  requirements:
    _permission: 'access content'

HTML

<a href="nojs/myFunction/testData" class="use-ajax">Click for testData!</a>

My understanding is that Drupal injects some sort of event when that link is clicked, or the URL is just changed, and the controller is only activated when that URL is changed.

JavaScript

(function($, Drupal) {

  Drupal.AjaxCommands.prototype.myFunction = function(ajax, response, status){

    $('#targetDiv').html(response.data);
  }

})(jQuery, Drupal);

I omitted PHP code for the controller, which creates a command. The command renders the output to Drupal.AjaxCommands.prototype.myFunction, which updates the div.

Is an XMLHttpRequest the only way to make JavaScript interact with the route/PHP? If so, what path should be used?

I think there might be a way for JavaScript interact with Drupal's AJAX handler to call the same function that clicking the link changed with "use-ajax" does, since that's being handled in some way...

Any insight would be appreciated.

Thanks!

1 Answer 1

17

If you don't want to ajaxify a link by adding the class use-ajax you can trigger an Ajax request programmatically:

Drupal.ajax({url: endpoint}).execute();

This creates an Ajax object with the endpoint as url and executes it. The endpoint has to be a controller returning an AjaxResponse.

You find more options in the comments of Drupal.ajax in ajax.js:

/**
   * Provides Ajax page updating via jQuery $.ajax.
   *
   * This function is designed to improve developer experience by wrapping the
   * initialization of {@link Drupal.Ajax} objects and storing all created
   * objects in the {@link Drupal.ajax.instances} array.
   *
   * @example
   * Drupal.behaviors.myCustomAJAXStuff = {
   *   attach: function (context, settings) {
   *
   *     var ajaxSettings = {
   *       url: 'my/url/path',
   *       // If the old version of Drupal.ajax() needs to be used those
   *       // properties can be added
   *       base: 'myBase',
   *       element: $(context).find('.someElement')
   *     };
   *
   *     var myAjaxObject = Drupal.ajax(ajaxSettings);
   *
   *     // Declare a new Ajax command specifically for this Ajax object.
   *     myAjaxObject.commands.insert = function (ajax, response, status) {
   *       $('#my-wrapper').append(response.data);
   *       alert('New content was appended to #my-wrapper');
   *     };
   *
   *     // This command will remove this Ajax object from the page.
   *     myAjaxObject.commands.destroyObject = function (ajax, response, status) {
   *       Drupal.ajax.instances[this.instanceIndex] = null;
   *     };
   *
   *     // Programmatically trigger the Ajax request.
   *     myAjaxObject.execute();
   *   }
   * };
   *
   * @param {object} settings
   *   The settings object passed to {@link Drupal.Ajax} constructor.
   * @param {string} [settings.base]
   *   Base is passed to {@link Drupal.Ajax} constructor as the 'base'
   *   parameter.
   * @param {HTMLElement} [settings.element]
   *   Element parameter of {@link Drupal.Ajax} constructor, element on which
   *   event listeners will be bound.
   *
   * @return {Drupal.Ajax}
   *   The created Ajax object.
   *
   * @see Drupal.AjaxCommands
   */
  Drupal.ajax = function (settings) {

Your second question, is an XMLHttpRequest the only way to make JavaScript interact with the route/PHP? If so, what path should be used?

You can use a normal non drupal $.ajax(), then you have no restrictions for the format. The controller can return JSON (which Drupal uses for it's own ajax) or any other format. It's then your job to process the returned data in javascript.

3
  • 2
    Thanks, Drupal.ajax({url: endpoint}).execute(); was exactly what I needed. The rest of the information will also be helpful going forward.
    – user70961
    Mar 5, 2017 at 1:26
  • 2
    YES OH god yes thanks , i made full example in docs api.drupal.org/comment/65246#comment-65246
    – taggartJ
    Jul 1, 2019 at 2:59
  • How do you attach behaviours to this modal ?
    – Teenage
    Jul 4, 2022 at 12:12

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.