Jak uniknąć „Wykryto nielegalny wybór” podczas aktualizacji wybranych wartości listy za pośrednictwem ajax?

10

Mam cztery pola odniesienia encji do encji użytkownika w formularzu. Formularz hosta to formularz edycji węzła. Trzy z nich to wybrane listy, ostatnia to formularz podmiotu wbudowanego .

Po dodaniu encji użytkownika za pośrednictwem IEF próbuję zaktualizować wartości wybranych list:

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);
}

Działa, ale kiedy próbuję dodać innego użytkownika za pośrednictwem IEF, otrzymuję:

Wykryto nielegalny wybór. Proszę skontaktować się z administratorem serwisu.

Codium
źródło
czy którekolwiek z Relatedpytań tutaj wymienionych po prawej stronie rozwiązało to?
Jimajamma,
@Jimajamma wygląda na to, że w przypadku oddzwaniania formularza ajax odbudowanie nie działa. Jak mogę to włączyć? $ form_state ['rebuild'] = PRAWDA nic nie rób ...
Codium
@Jajajamma, więc powiązane rozwiązania nie działają
Codium
Odpowiedziałem tutaj na twoje pytanie, ponieważ jest to duplikat pytania drupal.stackexchange.com/questions/15989/…
Sina Salek

Odpowiedzi:

15

--- Oryginalna odpowiedź. Jest źle, sprawdź aktualizację poniżej.

Właśnie ustawiłem

$bla['#validated'] = TRUE

Na wybranych, które będą aktualizowane za pomocą AJAX.

Kasa „Wykryto nielegalny wybór”

--- Aktualizacja 17 grudnia 2019 ---

Właściwie to nie była dobra rada, dawno temu, teraz wiem lepiej.

Funkcja wywołania zwrotnego Ajax ma zwracać tylko zmieniony formularz lub niektóre komendy ajax.

W takim przypadku należy zmodyfikować formularz w funkcji formularza lub haka do zmiany formularza. Funkcje budowania formularzy i sprawdzania poprawności są uruchamiane za każdym razem, gdy wywoływane jest wywołanie zwrotne ajax. Po prostu sprawdź $ form_state w funkcji budowania lub zmieniania formularzy i odpowiednio dostosuj wartości.

Zobacz Rozwiązywanie błędu „Wykryto nielegalny wybór ...”

jaimealsilva
źródło
1
Jeśli dobrze pamiętam, próbowałem tego, bez powodzenia w moim przypadku, dzięki
Codium
1
Obawiam się, że to też nie działa dla mnie.
kevin.coyle
Czy to nie czyni formularza mniej bezpiecznym?
Binny
Tak, wszystkie poprzednie komentarze są prawidłowe. Odpowiedź została zaktualizowana.
jaimealsilva,
3

Wiele razy napotykałem ten problem w Drupal 6, zmieniając wartości listy Select przez Ajax.

Oto, co możesz zrobić

  1. Jeśli to możliwe, spróbuj wstawić wszystkie możliwe wartości w interfejsie API pola, musisz edytować to pole, a następnie, gdy zmienisz wartości, musisz upewnić się, że tylko wymienione wartości znajdują się na liście.
  2. Rozwiązaniem, które wdrożyłem było, możesz zmienić typ pola z Wybierz listę na pole tekstowe, z Field API i poprosić Drupala o zapisanie wartości bez zmian. Teraz w środowisku wykonawczym formularza będziesz musiał zmienić formularz, zmienić typ, aby wybrać listę, i wcisnąć opcje, które chcesz. Podczas przesyłania również będziesz musiał przypisać poprawną wartość wymaganą przez pole, która zostanie zapisana w DB bez zmian. Upewnij się, że program obsługi przesyłania jest wywoływany przed domyślnym programem obsługi przesyłania formularza, którego możesz użyćarray_merge

Jeśli pierwsze rozwiązanie zadziała, zaoszczędzisz dużo czasu na kodowaniu i testowaniu. ALE jeśli lista rozwijana jest dynamiczna i nie masz nad nią kontroli, być może będziesz musiał wybrać drugie rozwiązanie.

Napisz, jeśli napotkasz jakiekolwiek problemy, wykonałem sporo pracy nad tym problemem, w moim projekcie i wykonałem ~ 50 formularzy, PHEW !!! :)

Vaibhav Jain
źródło
3

Znalazłem najlepszy sposób, aby to ustawić #valuena liście wyboru.

Jeśli mamy wartość w formstate i jest ona w naszych opcjach, nie otrzymamy błędu. Jeśli naszej wartości nie ma w opcjach, wybierz pierwszą opcję w naszych opcjach i skorzystaj z niej.

$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),
  );
Kok
źródło
2

Moje rozwiązanie:

/**
 * 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
źródło
-1

W wywołaniu zwrotnym ajax dodaj:

...

drupal_get_messages();
form_get_errors();

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

Ze względów bezpieczeństwa _form_validate()funkcja podstawowa sprawdza, czy klucz #options elementu zmienił się w stosunku do tego, co ustawiono w oryginalnej kompilacji (którą mają). Dzwoniąc drupal_get_messages()i po form_get_errors()prostu mówimy Drupalowi, aby ignorował wszelkie błędy / komunikaty podczas uruchamiania naszego żądania ajax. :)

JC3
źródło
Komunikat o błędzie zniknął, ale element select nadal zawiera klasę błędu. Jak usunąć lub zapobiec?
Tejas Vaidya,
Jest to odpowiednik Drupala nakładania taśmy na lampkę ostrzegawczą na desce rozdzielczej pojazdu.
Frank Robert Anderson