Know everything about Drupal Ajax Framework

About Me

  • Mahesh Sankhala, Full Stack Developer at Srijan Technologies PVT LTD
  • Working with Drupal from D6, D7 and D8
  • I love working with Css and Javascript. Making stuff with React these days

@MutantMahesh

https://www.drupal.org/u/msankhala

Agenda

  • What is Drupal ajax Framework?
  • Difference between D7 and D8 ajax framework
  • What are drupal ajax callback commands?
  • Create your custom ajax callback command

Ajax request workflow

Repetitive task

  1. Prepare ajax request object specify method and data
  2. After processing data at server decide format of response
  3. Proper encoding of HTML string
  4. Parse response and extract data
  5. Modify DOM - Prepend, Append, Delete, Show-Hide, Change Style

Ajax framework

  • Simplify and standardise this process
  • Provide simple API to attach ajax behaviour to any element on page
  • Standard way of returning response
  • Client side code + Server Side Code

Client Side

  1. Drupal.ajax() which is essentially a wrapper around $.ajax()
  2. Takes 3 arguments base, element, element_settings
// misc/ajax.js
Drupal.ajax = function (base, element, element_settings) {
  var defaults = {
    url: 'system/ajax',
    event: 'mousedown',
    keypress: true,
    selector: '#' + base,
    effect: 'none',
    speed: 'none',
    method: 'replaceWith',
    progress: {
      type: 'throbber',
      message: Drupal.t('Please wait...')
    },
    submit: {
      'js': true
    }
  };
 ...

Client Side

  1. A javascript function under Drupal.ajax.prototype.commands object
  2. Takes 3 arguments ajax, response, status
// misc/ajax.js

Drupal.ajax.prototype.commands = {
  /**
   * Command to remove a chunk from the page.
   */
  remove: function (ajax, response, status) {
    var settings = response.settings || ajax.settings || Drupal.settings;
    Drupal.detachBehaviors($(response.selector), settings);
    $(response.selector).remove();
  },
  ...
}

Server Side

  1. PHP function which returns associative array with key 'command' which represent Javascript function name
  2. Other element of array represent response data
// includes/ajax.inc

function ajax_command_remove($selector) {
  return array(
    'command' => 'remove',
    'selector' => $selector,
  );
}

function ajax_command_append($selector, $html, $settings = NULL) {
  return array(
    'command' => 'insert',
    'method' => 'append',
    'selector' => $selector,
    'data' => $html,
    'settings' => $settings,
  );
}

Attach ajax behaviour to field

Drupal gives 3 ways of making ajax request

  1. Add 'use-ajax' class to any anchor tag
  2. Add 'use-ajax-submit' to any form submit button
  3. Use '#ajax' render element to any field definition

'use-ajax' class on anchor tag

  1. When using 'use-ajax' class make sure drupal.ajax library is loaded on page.
  2. The href of the link can contain '/nojs/' as part of the path
$wrapper['link'] = array(
  '#markup' => l(
    t('Click me to load via ajax'),
    '<some/drupal/internal/path>',
    array(
      'attributes' => array('class' => 'use-ajax'),
    )
  ),
);

drupal_add_library('system', 'drupal.ajax');

// or

$wrapper['#attached']['library'] = array(
  array('system', 'drupal.ajax')
);

'use-ajax-submit' class on form submit

  1. When using 'use-ajax-submit' class make sure drupal.ajax and jquery.form library is loaded on page.
  2. The form will then be submitted via Ajax to the path specified in the #action and this path may contain '/nojs/' as part of the path.

 

$form['submit'] = array(
  '#type' => 'submit',
  '#value' => t('Save'),
  '#attributes' => ['class' => ['use-ajax-submit']],
);

drupal_add_library('system', 'drupal.ajax');
drupal_add_library('system', 'jquery.form');

// or

$form['#attached']['library'] = array(
  array('system', 'drupal.ajax')
);
$form['#attached']['library'] = array(
  array('system', 'jquery.form')
);

'#ajax' item on render element

This path may contain '/nojs/' as part of the path.

'#ajax' => array(
  'path' => 'some/drupal/path/nojs', // optional. default to 'system/ajax'. 
                                     // If specified, you must set up the menu entry 
                                     // and handle the entire callback

  'callback' => 'ajax_response_callback',
  'wrapper' => 'replace_textfield_div', // id of element to replace
  'method' => 'replaceWith' // optional. 
  'effect' => 'fade', // optional
  'event' => 'click', // optional
  'prevent' => 'click', // optional
  'progress' => array( // optional
    'type' => 'bar',
    'message' => 'Loading...',
    'url' => '</url/returning/progress/and/message>',
    'interval' => 1000
  ),
),

Server respond with Ajax Commands

function ajax_response_callback() {
  $commands = array();
  $commands[] = ajax_command_append('#selector', "Stuff...");
  $commands[] = ajax_command_replace("#wrapper", "replaced content" );
  return array('#type' => 'ajax', '#commands' => $commands);
}

// include/ajax.inc
function ajax_command_append($selector, $html, $settings = NULL) {
  return array(
    'command' => 'insert',
    'method' => 'append',
    'selector' => $selector,
    'data' => $html,
    'settings' => $settings,
  );
}

Steps to use ajax commands

  1. Attach ajax behaviour to dom element
  2. Attach drupal ajax library 
  3. Define a callback function at server side
  4. Return ajax commands

Ajax Commands in D8

// core/misc/ajax.js

Drupal.AjaxCommands.prototype = {
  remove: function (ajax, response, status) {
    var settings = response.settings || ajax.settings || drupalSettings;
    $(response.selector).each(function () {
      Drupal.detachBehaviors(this, settings);
    })
      .remove();
  },
...
}

// In Drupal 7 it was  Drupal.ajax.prototype.commands = {...}

Client side

Ajax Commands in D8

Server Side

  1. Ajax Commands are PHP objects that implements  Drupal\Core\Ajax\CommandInterface
  2. Implement a single method render() which returns an array with 'command' key which represent javascript function in Drupal.AjaxCommands.prototype

 

Steps to use ajax commands in D8

  1. Attach ajax behaviour to dom element
  2. Attach drupal ajax library 
  3. Define a route
  4. Define a controller method or Form
  5. Create Drupal\Core\Ajax\AjaxResponse object
  6. Add ajax commands with $response->addCommand method on AjaxResponse object

Enough Talk

Show me code

Create Custom Ajax Command in D8

Questoins

Send Feedback @MutantMahesh

Made with Slides.com