1

In Drupal 8, I want to generate options of second select-box based on Ajax call of first select-box. The result generate a third new select box but I don't need to generate a new one. I want to replace the options of the second select-box. Please see my codes below:

public function buildForm(array $form, FormStateInterface $form_state) {
$form['example_select'] = [
  '#type' => 'select',
  '#title' => $this->t('Select element'),
  'wrapper' => 'first',
  '#options' => [
    '1' => $this->t('One'),
    '2' => $this->t('Two'),
    '3' => $this->t('Three'),
    '4' => $this->t('From New York to Ger-ma-ny!'),
  ],
  '#ajax' => [
    'callback' => '::myAjaxCallback', 
    'disable-refocus' => FALSE, 
    'event' => 'change',
    'wrapper' => 'edit-output', 
    'progress' => [
      'type' => 'throbber',
      'message' => $this->t('Verifying entry...'),
    ],
  ]
];


$form['example_select2'] = [
  '#type' => 'select',
  '#title' => $this->t('Select element'),
  '#prefix' => '<div id="first">',
  '#suffix' => '</div>',
  '#options' => [
  ],
  '#ajax' => [
    'callback' => '::myAjaxCallback2', 
    'disable-refocus' => FALSE,
    'event' => 'change',
    'wrapper' => 'edit-output', 
    'progress' => [
      'type' => 'throbber',
      'message' => $this->t('Verifying entry...'),
    ],
  ]
];
return $form;
}

public function myAjaxCallback(array &$form, FormStateInterface $form_state) {
  if ($selectedValue = $form_state->getValue('example_select')) {
    $arr = array('1' => 'Nice way', '2' => 'Good way');
    $form['example_select2']['#options'] = $arr;
  }
  return $form['example_select2'];
}
0

The below code is working well forme.

public function myAjaxCallback(array &$form, FormStateInterface $form_state) {
  if ($selectedValue = $form_state->getValue('example_select')) {
    $arr = array('1' => 'Nice way', '2' => 'Good way');
    $form['example_select2']['#options'] = $arr;
  }
  $form_state->setRebuild(TRUE);
  $response = new AjaxResponse();
  $response->addCommand(new ReplaceCommand("#first", ($form['example_select2'])));
  return $response;
}
0
  1. Remove the 'wrapper' => 'first' that exist in the example_select.
  2. Set '#ajax'=> 'wrapper' elements to 'first', actually this is the id of element that will be updated, in your case <div id="first"> that you create using the prefix and suffix in $form['example_select2']
  3. This is an extra step, for some reason it will work but you'll get an error if you don't add '#validated' => 'true', to $form['example_select2']
  4. in the ajax callback function myAjaxCallback you need to apply some logic that enables you to create form select options dynamically based on the choice you made in the first slect box (see the code bellow )

full code that has been tested in my machine and it works 100% :

enter image description here

 public function buildForm(array $form, FormStateInterface $form_state) {
    $form['example_select'] = [
      '#type' => 'select',
      '#title' => $this->t('Select element'),
      '#options' => [
        '1' => $this->t('One'),
        '2' => $this->t('Two'),
        '3' => $this->t('Three'),
        '4' => $this->t('From New York to Ger-ma-ny!'),
      ],
      '#ajax' => [
        'callback' => '::myAjaxCallback',
        'disable-refocus' => FALSE,
        'event' => 'change',
        'progress' => [
          'type' => 'throbber',
          'message' => $this->t('Verifying entry...'),
        ],
        // The wrapper actually is the id of the element that
        // the ajax response will be injected into
        // it must be isndie the '#ajax" element.
        'wrapper' => 'first',
      ],
    ];

    $form['example_select2'] = [
      '#type' => 'select',
      '#title' => $this->t('Select element'),
      // The "wrapper" id that the ajax response will be injected into
      // must have an id ="wrapper set on select 1 form'.
      '#prefix' => '<div id="first">',
      '#suffix' => '</div>',
      // for some reason you  need to set '#validated' => 'true' other wise tou get :
      // An illegal choice has been detected. Please contact the site administrator.
      '#validated' => 'true',
      '#options' => [],
      '#ajax' => [
        'callback' => '::myAjaxCallback2',
        'disable-refocus' => FALSE,
        'event' => 'change',
        'wrapper' => 'edit-output',
        'progress' => [
          'type' => 'throbber',
          'message' => $this->t('Verifying entry...'),
        ],
      ],
    ];
    return $form;
  }

  public function myAjaxCallback(array &$form, FormStateInterface $form_state) {
    // 1.construct an array of choices
    // make the key = your select '#options' key
    // and value = options values that you want to use in example_select2.
    $arr = [
      '1' => ['first','uno','first one','Best'],
      '2' => ['Second','2nd place','not first'],
      '3' => ['Third','Three',''],
      '4' => ['Fourth','four','las one'],
    ];

    // 2.Get the selected option value
    // ex : 3
    $selctedOption = $form_state->getValue("example_select");

    // 3.Choose an array based on the selected option value.
    // ex : $arr['3']
    $form['example_select2']['#options'] = $arr[$selctedOption];

    return $form['example_select2'];
  }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.