By: Prafull Ranjan
January 10 2018

How To Use AJAX API in Drupal 8?

What is AJAX?
It’s not a programming language but a combination of – browser built-in XML HttpRequest object, Javascript, and DOM. It allows updating parts of the webpage instead of refreshing the whole webpage.
 

Working of AJAX working between Server and HTML page
Source: Drupal.org

A lot of people confuse AJAX with a programming language. No, it's not a programming language but it's a combination of browser built-in XMLHttpRequest object, Javascript, and DOM.

It allows updating parts of the webpage instead of refreshing the whole webpage.

Many different events trigger AJAX like

  1. Clicking a button
  2. Pressing a key
  3. Moving the mouse

Also, there are a few elements of AJAX which need to be covered before proceeding further. They are

  • Callback
  • Wrapper
  • Method
  • Effect
  • Speed
  • Event
  • Prevent
  • Progress
  • Type
  • URL 

In Drupal, AJAX responses can be triggered by forms that use Drupal Form API. Here are steps for AJAX call in Drupal:

  1. Add property ‘#ajax’ to a form element in your form array, to trigger an AJAX response.     
  2. Write an AJAX call-back to process the input and response.

Most used AJAX classes
Here are some of the most used Ajax classes in Drupal to make your Ajax calls easier:

  1. AjaxResponse: JSON response object for AJAX requests.
  2. HtmlCommand: AJAX command for calling the jQuery html() method.
  3. InvokeCommand: AJAX command for invoking an arbitrary jQuery method.
  4. AddCssCommand: An AJAX command for adding CSS to the page via ajax.
  5. SettingsCommand: AJAX command for adjusting Drupal's JavaScript settings.
  6. PrependCommand: AJAX command for calling the jQuery insert() method.

Setting up a callback to process AJAX

After the form is set to trigger the Ajax response, write the following PHP codes to process the responses.
  
If you use 'path' in your Ajax set-up, your route controller will be triggered with only the information you provide in the URL.

If you use 'callback', your callback method is a function, which will receive the $form and $form_state from the triggering form. 

You can use $form_state to get information about the data the user has entered into the form.
  
In our example, the function Drupal\ajax_module\Form\AjaxModuleForm::usernameValidateCallback does this to check the username:

    $form_state->getValue('user_name') - It’ll get the value from the text-fields in the $form['user_name'] array. If the user is found, this function will set the markup value & color as
    $text = 'User Found';
    $color = 'green';

If the user is not found, this function will set them as
    $text = 'No User Found';
    $color = 'red';

Now, if the input is processed, you can return the HTML markup or AJAX commands.
If you choose to return HTML markup, you can return it as a string or a renderable array, and it will be placed in the defined 'wrapper' element. In addition, any messages returned by drupal_get_messages(), themed as in status-messages.html.twig, will be prepended.

Now, to return a command, you need to set up an object of class \Drupal\Core\Ajax\AjaxResponse, and then use its addCommand() method to add individual commands according to your wish. In our example, we’ve used the command as: 
$ajax_response->addCommand(new HtmlCommand('#edit-user-name--description', $text));
$ajax_response->addCommand(new InvokeCommand('#edit-user-name--description', 'css', array('color', $color)));
The former replaces the username description while the later changes the color of that description.

Let’s, now, create a custom form that will contain a text field that will validate if the username exists.

If the username already exists, it’ll display a message in green color else will display the message in red.

1.     ajax_module.info.yml
name: Ajax Module
description: ‘Ajax module to validate username’
core: 8.x
type: module

2.     ajax_module.routing.yml

ajax_module.form
    path: '/admin/ajax_module’
defaults:
    _form: 'Drupal\ajax_module\Form\AjaxModuleForm'
    _title: 'Ajax Module’
requirements:
    _permission: 'access administration pages'


3.     src/Form/AjaxModuleForm.php

<?php
/**
 * @file
 * Contains Drupal\ajax_module\AjaxModuleForm
 */
namespace Drupal\ajax_module\Form;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ChangedCommand;
use Drupal\Core\Ajax\CssCommand;
use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
class AjaxModuleForm extends FormBase {
  public function getFormId() {
	return 'ajax_module_form';
  }
  public function buildForm(array $form, FormStateInterface $form_state) {
	$form['user_name'] = array(
  	'#type' => 'textfield',
  	'#title' => 'Username',
  	'#description' => 'Please enter in a username',
  	'#ajax' => array(
    	// Function to call when event on form element triggered.
    	'callback' => 'Drupal\ajax_module\Form\AjaxModuleForm::usernameValidateCallback',
    	// Effect when replacing content. Options: 'none' (default), 'slide', 'fade'.
    	'effect' => 'fade',
    	// Javascript event to trigger Ajax. Currently for: 'onchange'.
    	'event' => 'change',
    	'progress' => array(
      	// Graphic shown to indicate ajax. Options: 'throbber' (default), 'bar'.
      	'type' => 'throbber',
      	// Message to show along progress graphic. Default: 'Please wait...'.
      	'message' => NULL,
    	),
  	),
	);
	return $form;
  }
 
  public function submitForm(array &$form, FormStateInterface $form_state) {
	drupal_set_message('Nothing Submitted. Just an Example.');
  }
 
  public function usernameValidateCallback(array &$form, FormStateInterface $form_state) {
	// Instantiate an AjaxResponse Object to return.
	$ajax_response = new AjaxResponse();
	
	// Check if Username exists and is not Anonymous User ('').
	if (user_load_by_name($form_state->getValue('user_name')) && $form_state->getValue('user_name') != false) {
  	$text = 'User Found';
  	$color = 'green';
	} else {
  	$text = 'No User Found';
  	$color = 'red';
	}
	
	// Add a command to execute on form, jQuery .html() replaces content between tags.
	// In this case, we replace the desription with wheter the username was found or not.
    $ajax_response->addCommand(new HtmlCommand('#edit-user-name--description', $text));
	
	// Add a command, InvokeCommand, which allows for custom jQuery commands.
	// In this case, we alter the color of the description.
    $ajax_response->addCommand(new InvokeCommand('#edit-user-name--description', 'css', array('color', $color)));
	
	// Return the AjaxResponse Object.
	return $ajax_response;
  }
}