Skip to main content

Drupal has adopted Ajax, review how it implemented in Forms

Overview of Ajax

Ajax is the process of dynamically updating parts of a page's HTML based on data from the server. When a specified event takes place, a PHP callback is triggered, which performs server-side logic and may return updated markup or JavaScript commands to run. After the return, the browser runs the JavaScript or updates the markup on the fly, with no full page refresh necessary.

Many different events can trigger Ajax responses, including:

  • Clicking a button
  • Pressing a key
  • Moving the mouse

 

Ajax responses in forms

Forms that use the Drupal Form API (see the Form API topic for more information about forms) can trigger AJAX responses. Here is an outline of the steps:

  • Add property '#ajax' to a form element in your form array, to trigger an Ajax response.
  • Write an Ajax callback to process the input and respond.

See sections below for details on these two steps.

Adding Ajax triggers to a form

As an example of adding Ajax triggers to a form, consider editing a date format, where the user is provided with a sample of the generated date output as they type. To accomplish this, typing in the text field should trigger an Ajax response. This is done in the text field form array element in \Drupal\config_translation\FormElement\DateFormat::getFormElement():

'#ajax' => [
   'callback' => 'Drupal\config_translation\FormElement\DateFormat::ajaxSample',
   'event' => 'keyup',  
   'progress' => [ 'type' => 'throbber', 'message' => NULL,  ], 
 ],

 

Setting up a callback to process Ajax

Once you have set up your form to trigger an Ajax response (see Adding Ajax triggers to a form above), you need to write some PHP code to process the response. 
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. 
For instance, in the above example for the date format preview, \Drupal\config_translation\FormElement\DateFormat\ajaxSample() does this to get the format string entered by the user:

$format_value = \Drupal\Component\Utility\NestedArray::getValue($form_state  ->getValues(), 
$form_state->getTriggeringElement()['#array_parents']);

Once you have processed the input, you have your choice of returning HTML markup or a set of 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 (see documentation above in Adding Ajax triggers to a form). 
In addition, any messages returned by \Drupal\Core\Messenger\Messenger::all(), themed as in status-messages.html.twig, will be prepended.

To return commands, you need to set up an object of class \Drupal\Core\Ajax\AjaxResponse, and then use its addCommand() method to add individual commands to it. 
In the date format preview example, the format output is calculated, and then it is returned as replacement markup for a div like this:

$response = new AjaxResponse(); 
$response->addCommand(new ReplaceCommand('#edit-date-format-suffix', '<small id="edit-date-format-suffix">' . $format . '</small>')); 
return $response;

The individual commands that you can return implement interface \Drupal\Core\Ajax\CommandInterface. Available commands provide the ability to pop up alerts, manipulate text and markup in various ways, redirect to a new URL, and the generic \Drupal\Core\Ajax\InvokeCommand, which invokes an arbitrary jQuery command.

As noted above, status messages are prepended automatically if you use the 'wrapper' method and return HTML markup. This is not the case if you return commands, but if you would like to show status messages, you can add

array(  '#type' => 'status_messages', );

to a render array, use \Drupal::service('renderer')->render() to render it, and add a command to place the messages in an appropriate location.

read more at Ajax API

$response = new AjaxResponse(); 
$response->addCommand(new ReplaceCommand('#edit-date-format-suffix', '<small id="edit-date-format-suffix">' . $format . '</small>')); 
return $response;
'#ajax' => [
  'callback' => 'Drupal\config_translation\FormElement\DateFormat::ajaxSample',
  'event' => 'keyup',  
  'progress' => [ 'type' => 'throbber', 'message' => NULL,  ], 
],