Как избежать «Обнаружен неправильный выбор» при обновлении значений списка выбора через ajax?

10

У меня есть четыре поля ссылки на сущность пользователя в форме. Форма хоста - это форма редактирования узла. Три из них являются списками выбора, последний - Inline Entity Form .

После добавления пользовательского объекта через IEF я пытаюсь обновить значения списков выбора:

function ebep_users_feature_users_list_ajax($form, $form_state) {

  $ief = array_shift($form_state['inline_entity_form']);
  $options = array('_node' => t('- None -'));
  $commands = array();

  foreach($ief['entities'] as $data) {
    $options[$data['entity']->uid] = $data['entity']->name;
  }

  foreach(_ebep_users_feature_getUserListFieldNames() as $fieldName) {
    $form[$fieldName]['und']['#options'] = $options;
    $commands[] = ajax_command_replace('#'.$fieldName.'_wrapper', drupal_render($form[$fieldName]));
  }

  return array('#type' => 'ajax', '#commands' => $commands);
}

Это работает, но когда я пытаюсь добавить другого пользователя через IEF, я получаю:

Обнаружен незаконный выбор. Пожалуйста свяжитесь с администратором сайта.

Codium
источник
Есть ли какие-либо из Relatedвопросов, перечисленных здесь, чтобы решить эту проблему?
Jimajamma
@Jimajamma кажется, что перестроение формы обратного вызова в ajax не работает. Как я могу включить это? $ form_state ['rebuild'] = TRUE ничего не делать ...
Codium
@Jimajamma, поэтому связанные решения не работают
Codium
Я ответил на ваш вопрос здесь, так как это дублирующий вопрос drupal.stackexchange.com/questions/15989/…
Сина Салек

Ответы:

15

--- Оригинальный ответ. Неправильно, проверьте обновление ниже.

Просто установите

$bla['#validated'] = TRUE

На выбор, который будет обновлен с AJAX.

Оформить заказ "Незаконный выбор был обнаружен"

--- Обновление 17 декабря 2019 года ---

На самом деле это был не очень хороший совет, это было давно, теперь я знаю лучше.

Функция обратного вызова Ajax должна возвращать только часть измененной формы или некоторые команды ajax.

В этом случае необходимо изменить форму в функции формы или в хуке изменения формы. Функции построения и проверки форм выполняются каждый раз, когда вызывается обратный вызов ajax. Просто проверьте $ form_state в вашей сборке формы или измените функцию и измените значения соответствующим образом.

См. Устранение ошибки «Обнаружен незаконный выбор ...»

jaimealsilva
источник
1
Если я хорошо помню, я попробовал это, но безуспешно в моем случае, спасибо
Codium
1
Боюсь, это тоже не работает для меня.
kevin.coyle
Разве это не делает форму менее безопасной?
Бинни
Да, все предыдущие комментарии верны. Ответ был обновлен.
Jaimealsilva
3

Я сталкивался с этой проблемой несколько раз в Drupal 6, меняя значения списка выбора через Ajax.

Вот что вы можете сделать, это

  1. Если возможно, попробуйте вставить все возможные значения в поле API поля, вам нужно отредактировать это поле, а затем при изменении значений вам нужно будет убедиться, что в списке присутствуют только перечисленные значения.
  2. Решение, которое я реализовал, состояло в том, что вы можете изменить тип поля с Select list на textfield, с Field API и попросить Drupal сохранить значение как есть. Теперь во время выполнения формы вам нужно будет изменить форму, изменить тип, чтобы выбрать список, и нажать опции, которые вы хотите. Во время отправки вам также нужно будет указать правильное значение, необходимое для поля, которое будет сохранено в БД как есть. Убедитесь, что ваш обработчик отправки вызывается перед обработчиком отправки формы по умолчанию, для этого вы можете использоватьarray_merge

Если первое решение работает для вас, вы сэкономите много времени на программировании и тестировании. НО, если список в раскрывающемся списке является динамическим, и вы не можете его контролировать, возможно, вам придется использовать второе решение.

Пишите, если у вас возникнут какие-либо проблемы, я проделал довольно много работы над этой проблемой для своего проекта, и я сделал для ~ 50 форм, PHEW !!! :)

Вайбхав Джайн
источник
3

Я нашел лучший способ обойти это, чтобы установить #valueв списке выбора.

Если у нас есть значение в formtate и оно есть в наших параметрах, мы не получим ошибку. Если наше значение отсутствует в параметрах, выберите первый вариант в наших параметрах и используйте его.

$form['example'] = array(
    '#type' => 'select',
    '#title' => t('Example'),
    '#options' => $options,
    '#value' => isset($form_state['values']['example']) && in_array($form_state['values']['example'],$options)?$form_state['values']['example']:key($options),
  );
боб
источник
2

Мое решение:

/**
 * Implements hook_form_FORM_ID_alter()
 */
function ebep_users_feature_form_ebep_exhibitor_profile_node_form_alter(&$form, &$form_state, $form_id) {

  foreach(_ebep_users_feature_getUserListFieldNames() as $fieldName) {
    $form[$fieldName]['und']['#prefix'] = '<div id="'.$fieldName . '_wrapper">';
    $form[$fieldName]['und']['#suffix'] = '</div>';
    $form[$fieldName]['und']['#options'] = _ebep_users_feature_getOptionsValuesFromIEFList($form_state);
  }

  $form['#attached']['css'] = array(
    drupal_get_path('module', 'ebep_users_feature') . '/assets/styles.css',
  );

  $form['#attached']['js'] = array(
    drupal_get_path('module', 'ebep_users_feature') . '/assets/scripts.js',
  );

  $form['users_refresh'] = array(
    '#type' => 'submit',
    '#value' => t('Refresh users list'),
    '#ajax' => array(
      'callback' => 'ebep_users_feature_users_list_ajax',
    ),
  );
}

function ebep_users_feature_users_list_ajax($form, $form_state) {

  $commands = array();

  foreach(_ebep_users_feature_getUserListFieldNames() as $fieldName) {
    $form[$fieldName]['und']['#options'] = _ebep_users_feature_getOptionsValuesFromIEFList($form_state);
    $commands[] = ajax_command_replace('#'.$fieldName.'_wrapper', drupal_render($form[$fieldName]));
  }

  return array('#type' => 'ajax', '#commands' => $commands);
}

function _ebep_users_feature_getOptionsValuesFromIEFList($form_state) {
  static $options = array();

  if (empty($options)) {
    $ief = array_shift($form_state['inline_entity_form']);
    $options['_node'] = t('- None -');

    foreach($ief['entities'] as $data) {
      $options[$data['entity']->uid] = $data['entity']->name;
    }
  }

  return $options;
}
Codium
источник
-1

В ваш обратный вызов ajax добавьте:

...

drupal_get_messages();
form_get_errors();

return array('#type' => 'ajax', '#commands' => $commands);

В качестве меры безопасности основная _form_validate()функция проверяет, изменился ли ключ элемента #options по сравнению с тем, что было установлено в исходной сборке (которая у них есть). Позвонив drupal_get_messages()и form_get_errors()мы в основном сказать Drupal , чтобы игнорировать любые ошибки / сообщения во время работы нашего AJAX запроса. :)

х3
источник
Сообщение об ошибке исчезло, но элемент select по-прежнему содержит класс ошибки. Как это устранить или предотвратить?
Теджас Вайдья
Это эквивалент Drupal, который наносит ленту поверх сигнальной лампы на приборной панели вашего автомобиля.
Фрэнк Роберт Андерсон