“An illegal choice is detected…” error with dynamic dropdown select list I Drupal8

流过昼夜 提交于 2020-03-25 16:04:59

问题


I wrote this code for dynamic dropdown select list in hook_form_alter. Options are populated by an external DB.

function car2db_annuncio_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'node_annuncio_form') {
    $options_type = car2db_annuncio_type_dropdown_options();
    $form['field_marca']['#prefix'] = '<div id="field_marca">';
    $form['field_marca']['#suffix'] = '</div>';
    $form['field_tipologia']['widget']['#options'] = $options_type;
    $form['field_tipologia']['widget']['#ajax'] = array(
      'event' => 'change',
      'callback' => 'car2db_annuncio_make_ajax_callback',
      'wrapper' => 'field_marca',
      'disable-refocus' => FALSE,
      'progress' => [
        'type' => 'throbber',
        'message' => t('Verify...'),
      ]
    );
  }
}

function car2db_annuncio_type_dropdown_options() {
  $connection = Database::getConnection('default', 'migrate');

  $dropdown_type = ['none' => '- Seleziona - '];
  $sql_type = "SELECT * FROM `car_type`";
  $query_type = $connection->query($sql_type);
  $res_type = $query_type->fetchAll();
  foreach ($res_type as $row){
    $key = $row->id_car_type;
    $value = $row->name;

    $dropdown_type[$key] = $value;
  }
  return $dropdown_type;
}

function car2db_annuncio_make_dropdown_options($key_type) {
  $connection = Database::getConnection('default', 'migrate');

  $dropdown_make = ['none' => '- Seleziona - '];
    $sql_make = "SELECT * FROM `car_make` WHERE `id_car_type` = :tipo";
    $query_make = $connection->query($sql_make, [':tipo' => $key_type]);
    $res_make = $query_make->fetchAll();
    foreach ($res_make as $row){
      $Key_make = $row->id_car_make;
      $Make_value = $row->name;

      $dropdown_make[$Key_make] = $Make_value;
    }

  return $dropdown_make;
}

function car2db_annuncio_make_ajax_callback(array &$form, FormStateInterface $form_state) {
  if ($selectedValue = $form_state->getValue('field_tipologia')) {
    $selectedValue = (int) $selectedValue[0]['value'] ? (int) $selectedValue[0]['value'] : 0;
    $options_marca = car2db_annuncio_make_dropdown_options($selectedValue);
    $form['field_marca']['widget']['#options'] = $options_marca;
  }
  return $form['field_marca'];
}

Now, when click on "Save button", there is always "An illegal choice is detected...." error. I also tried loading options into the hook_form alter, but it always returns an error. Where am i wrong?


回答1:


I remember this confusing the hell out of me back in the day when I first started playing with ajax forms in Drupal.
Hopefully I am remembering this correctly.
Basically, you have to move your logic for adding the dynamic options into the form build function (but in your case, it's the alter function).
When the ajax function is called, the form is still rebuilt and your alter function is called (and has the current form_state).
Your ajax function will just return the new form element.
Something like below (untested)

function car2db_annuncio_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'node_annuncio_form') {
    $options_type = car2db_annuncio_type_dropdown_options();
    $form['field_marca']['#prefix'] = '<div id="field_marca">';
    $form['field_marca']['#suffix'] = '</div>';
    $form['field_tipologia']['widget']['#options'] = $options_type;
    $form['field_tipologia']['widget']['#ajax'] = array(
      'event' => 'change',
      'callback' => 'car2db_annuncio_make_ajax_callback',
      'wrapper' => 'field_marca',
      'disable-refocus' => FALSE,
      'progress' => [
        'type' => 'throbber',
        'message' => t('Verify...'),
      ]
    );
    // Check selected value here.
    if ($selectedValue = $form_state->getValue('field_tipologia')) {
      $selectedValue = (int) $selectedValue[0]['value'] ? (int) $selectedValue[0]['value'] : 0;
      $options_marca = car2db_annuncio_make_dropdown_options($selectedValue);
      $form['field_marca']['widget']['#options'] = $options_marca;
    }
  }
}

function car2db_annuncio_type_dropdown_options() {
  $connection = Database::getConnection('default', 'migrate');

  $dropdown_type = ['none' => '- Seleziona - '];
  $sql_type = "SELECT * FROM `car_type`";
  $query_type = $connection->query($sql_type);
  $res_type = $query_type->fetchAll();
  foreach ($res_type as $row){
    $key = $row->id_car_type;
    $value = $row->name;

    $dropdown_type[$key] = $value;
  }
  return $dropdown_type;
}

function car2db_annuncio_make_dropdown_options($key_type) {
  $connection = Database::getConnection('default', 'migrate');

  $dropdown_make = ['none' => '- Seleziona - '];
    $sql_make = "SELECT * FROM `car_make` WHERE `id_car_type` = :tipo";
    $query_make = $connection->query($sql_make, [':tipo' => $key_type]);
    $res_make = $query_make->fetchAll();
    foreach ($res_make as $row){
      $Key_make = $row->id_car_make;
      $Make_value = $row->name;

      $dropdown_make[$Key_make] = $Make_value;
    }

  return $dropdown_make;
}

function car2db_annuncio_make_ajax_callback(array &$form, FormStateInterface $form_state) {
  // Just return the form element (that has been rebuilt in the form_alter)
  return $form['field_marca'];
}


来源:https://stackoverflow.com/questions/60662918/an-illegal-choice-is-detected-error-with-dynamic-dropdown-select-list-i-dru

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!