Ajax Form | Drupal 8

Ajax Form

Submitted by editor on Wed, 11/18/2015 - 16:48
Question

How to Change a form using ajax ?

Exemple : Field 'username'

//Form
    $form['username'] = array(
      '#type' => 'textfield',
      '#title' => 'Your user name',
      '#description' => 'User name',
      '#ajax' => array(
        'callback' => '::checkUserNameAjax',
        'wrapper' => 'edit-username',
        'method' => 'replace',
        'effect' => 'fade',
        'event' => 'change',
      ),

      //If you want to change the ID
      '#prefix' => '<div id="edit-username">',
      '#suffix' => '</div>',
    );

1. Ajax Methode to Edit Form
  function checkUserNameAjax($form, FormStateInterface $form_state) {
    $form['username']['#description'] = "YES";
    return $form['username'];
  }

2. Or using AjaxResponse to change HTML/CSS

  function checkUserNameAjax(array &$form, FormStateInterface &$form_state) {
    $valid = rand(0,1);
    if ($valid) {
      $css = ['border' => '1px solid green'];
      $message = ('User name ok.');
    }else {
      $css = ['border' => '1px solid red'];
      $message = ('User name not valid.');
    }
    $response = new \Drupal\Core\Ajax\AjaxResponse();
    $response->addCommand(new \Drupal\Core\Ajax\CssCommand('#edit-username', $css));
    $response->addCommand(new \Drupal\Core\Ajax\HtmlCommand('#edit-username--description', $message));
    return $response;
  }

Example 2 : Change a title using selected value

public function buildForm(array $form, FormStateInterface $form_state) {
  $form['methods'] = array(
    '#type' => 'select',
    '#title' => $this->t('Method'),
    '#default_value' => "",
    '#options' => ["a"=>"A Value","b"=>"B Value",],
    '#ajax' => array(
      'callback' => '::methodChangeAjax',
      'wrapper' => 'edit-fieldsset',
      'method' => 'replace',
      'effect' => 'fade',
      'event' => 'change',
    ),
  );
//Ajax changable fields container
  $form['fieldsset'] = array(
    '#type' => 'fieldset',
    '#title' => $this->t('Fields'),
    '#default_value' => "",
    '#prefix' => '<div id="edit-fieldsset">',
    '#suffix' => '</div>',
  );
  return $form;
}
function methodChangeAjax($form, FormStateInterface $form_state) {
  $method = $form_state->getValue('methods');
  $form['fieldsset']['#title'] = $method;
  return $form['fieldsset'];
}

Comments

This happens if you add the fields on the callback function. The form doesn't get rebuilt at this point, so the values on the new fields are discarded. You need to add the fields on buildForm function by checking on the $form_state values.

On the simplest case, you can check that the triggering field has a value set and then conditionally build the new field as per defined functionality. Then on the callback you just need to call:

$form_state->setRebuild(true);
return $form['wrapper_of_the_element_to_change'];

Add new comment