Implement the Ajax callback function in Drupal 8/9

lakshmi , Credit to  volkotech-solutions Jun 06

Ajax API allows creating forms that are submitted to the server and processed without the need for a page reload. This API allows you to replace DOM elements with new HTML or run jQuery commands. By adding AJAX callback events to form fields, you can dynamically update fields and other markups as users interact with the forms.

Ajax callback functions: 

Depending on what you want to do in your AJAX callback, there are several ways to respond to the ajax request.

  • Render array: If you only want to update a single field on your form, simply return a render array, such as $form['field_yourfieldname']. The resulting markup will be placed in the wrapper element defined when the ['#ajax'] render array was attached to the form field.
  • Custom HTML markup: If you want to display information on your form that isn't related to a field, you can return HTML Markup that will be placed in the wrapper element defined when attaching the ['#ajax'] render array to the form field.
  • AJAX Command: If you don't want to update your form and instead use an AJAX Command, you must return an AjaxResponse object.

Implement Render Array Ajax callback:

For example, the Module name is ajax_branch_names and build a simple form with a select field that triggers an event whenever the user changes the selection. The selected value of the select field from the $form_state interface by the callback function and save to the output text field. Then we return a render array of the prepared text field. This replaces the original text field on the form.

Paste the following code in ajax_branch_names/src/Form/AjaxBranchNamesForm.php

<?php

namespace Drupal\ajax_branch_names\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;

/**
 * Provides a default form.
 */
class AjaxBranchNamesForm extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'ajax_branch_names_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    // Create a select field that will update the contents of the textbox below.
    $form['select_branch_name'] = [
      '#type' => 'select',
      '#title' => $this->t('Select Branch Name'),
      '#options' => [
        '1' => $this->t('CSE'),
        '2' => $this->t('IT'),
        '3' => $this->t('EEE'),
        '4' => $this->t('ECE'),
      ],
      '#ajax' => [
        'callback' => '::myAjaxCallback', // Use :: when calling a class method.
        'disable-refocus' => FALSE, // Or TRUE to prevent re-focusing on the triggering element.
        'event' => 'change',
        'wrapper' => 'edit-output', // wrapper element is updated with this AJAX callback.
        'progress' => [
          'type' => 'throbber',
          'message' => $this->t('Verifying entry...'),
        ],
      ]
    ];
    // Create a textbox that will be updated
    // when the user selects an item from the select box above.
    $form['output'] = [
      '#type' => 'textfield',
      '#size' => '60',
      '#disabled' => TRUE,
      '#value' => 'Branch Names',      
      '#prefix' => '<div id="edit-output">',
      '#suffix' => '</div>',
    ];

    // Create the submit button.
    $form['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
    ];
    return $form;
  }
  // Get the value from select_branch_name and fill the textbox with the selected text.
public function myAjaxCallback(array &$form, FormStateInterface $form_state) {
  // Prepare our textfield. check if the select_branch_name has a selected option.
  if ($selectedValue = $form_state->getValue('select_branch_name')) {
      // Get the text of the selected option.
      $selectedText = $form['select_branch_name']['#options'][$selectedValue];
      // Place the text of the selected option in our textfield.
      $form['output']['#value'] = $selectedText;
  }
  // Return the prepared textfield.
  return $form['output']; 
}

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    parent::validateForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    // Display result.
    foreach ($form_state->getValues() as $key => $value) {
      \Drupal::messenger()->addStatus($key . ': ' . $value);
    }
  }

}

Output:

render array

Implement HTML markup Ajax callback: 

You can return HTML markup instead of a render array if you don't want to change the value of a form field but instead want to display some custom HTML markup on your form. The returned markup completely replaces the object with the id specified as a wrapper in the #ajax render array, which is attached to the form field, so include the id specified as a wrapper in the ['#ajax'] render array in the custom markup returned from your callback.

Replace the textfield on the form with a DIV element containing the selected text in ajax_branch_names/src/Form/AjaxBranchNamesForm.php

public function myAjaxCallback(array &$form, FormStateInterface $form_state) {
 $markup = 'nothing selected';
 
 // Prepare our textfield. check if the select_branch_name has a selected option.
 if ($selectedValue = $form_state->getValue('select_branch_name')) {
     // Get the text of the selected option.
     $selectedText = $form['select_branch_name']['#options'][$selectedValue];
     // Place the text of the selected option in our textfield.
     $markup = "<h1>$selectedText</h1>";
 }
 
 // wrap your markup in a div with the #edit-output id.
 $output = "<div id='edit-output'>$markup</div>";
 
 // Return the HTML markup we built above in a render array.
 return ['#markup' => $output];
}

Output:

html markup

Implement AJAX Commands (AjaxResponse):

When your callback function is executed, you can also return an AjaxResponse that issues AJAX commands via the client-side jQuery library.

For example, Replace our original output textbox with a new textbox containing the selected text. Then it will display a modal dialog box with the text from our select form element selected.

Paste the following code in ajax_branch_names/src/Form/AjaxBranchNamesForm.php

// add namespace in your module.
use Drupal\Core\Ajax\OpenModalDialogCommand;
 
/**
* An Ajax callback.
*/
public function myAjaxCallback(array &$form, FormStateInterface $form_state) {
 // Try to get the selected text from the select element on our form.
 $selectedText = 'nothing selected';
 if ($selectedValue = $form_state->getValue('select_branch_name')) {
   // Get the text of the selected option.
   $selectedText = $form['select_branch_name']['#options'][$selectedValue];
 }
 
 // Create a new textfield element containing the selected text.
 $elem = [
   '#type' => 'textfield',
   '#size' => '60',
   '#disabled' => TRUE,
   '#value' => "I am a new textfield: $selectedText!",
   '#attributes' => [
     'id' => ['edit-output'],
   ],
 ];
 
 // Attach the javascript library for the dialog box command from drupal core.
 $dialogText['#attached']['library'][] = 'core/drupal.dialog.ajax';
 // Prepare the text for our dialogbox.
 $dialogText['#markup'] = "You selected: $selectedText";
 // create a AjaxResponse object.
 $response = new AjaxResponse();
 // ReplaceCommand() will take care of rendering our text field into HTML.
 $response->addCommand(new ReplaceCommand('#edit-output', $elem));
 // Show the dialog box.
 $response->addCommand(new OpenModalDialogCommand('Branch Name', $dialogText, ['width' => '300']));
 
 // Finally return the AjaxResponse object.
 return $response;
}

Output:

responseobject

Conclusion:

Ajax API enables the creation of forms that are submitted to the server and processed without requiring a page reload. In this blog, we explain how to use Ajax callback functions for example to improve our form and make it more user-friendly.

 

Comments