Como evitar "Uma escolha ilegal foi detectada" ao atualizar os valores da lista de seleção via ajax?

10

Eu tenho quatro campos de referência de entidade para entidade de usuário em um formulário. O formulário do host é o formulário de edição do nó. Três deles são listas de seleção; o último é o formulário de entidade embutida .

Depois de adicionar uma entidade de usuário via IEF, estou tentando atualizar os valores das listas de seleção:

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

Funciona, mas quando tento adicionar outro usuário via IEF, estou recebendo:

Uma escolha ilegal foi detectada. Entre em contato com o administrador do site.

Códio
fonte
alguma das Relatedperguntas aqui listadas à direita resolveu isso?
Jimajamma
@ Jimajamma parece que, no formulário de retorno de chamada ajax, a reconstrução não é um trabalho. Como posso habilitá-lo? $ form_state ['rebuild'] = VERDADEIRO não faça nada ...
Codium 9/12
@Jimajamma soluções para relacionadas não funciona
Codium
Eu respondi sua pergunta aqui, já que é uma pergunta duplicada drupal.stackexchange.com/questions/15989/…
Sina Salek

Respostas:

15

--- Resposta original. Está errado, verifique a atualização abaixo.

Basta definir

$bla['#validated'] = TRUE

Na seleção que será atualizada com o AJAX.

Caixa "A escolha ilegal foi detectada"

--- Atualização 17 dez 2019 ---

Na verdade, esse não foi um bom conselho, isso foi há muito tempo, agora eu sei melhor.

A função de retorno de chamada do Ajax deve retornar apenas o pedaço de formulário que foi alterado ou alguns comandos do ajax.

Nesse caso, a modificação do formulário deve ser feita na função de formulário ou em um gancho de alteração de formulário. As funções de criação e validação de formulário são executadas sempre que um retorno de chamada ajax é chamado. Basta verificar $ form_state na criação de seu formulário ou alterar a função e ajustar os valores de acordo.

Consulte Resolver o erro "Foi detectada uma escolha ilegal ..."

jaimealsilva
fonte
11
Se eu me lembro bem, eu tentei isso, sem sucesso, no meu caso, graças
Codium
11
Receio que isso também não funcione para mim.
precisa saber é o seguinte
Isso não torna o formulário menos seguro?
Binny
Sim, todos os comentários anteriores estão corretos. A resposta foi atualizada.
jaimealsilva
3

Já enfrentei esse problema várias vezes no Drupal 6, alterando os valores da lista de seleção via Ajax.

Aqui está o que você pode fazer é

  1. Se possível, tente inserir todos os valores possíveis na API do campo, você precisará editar esse campo e, quando alterar os valores, precisará garantir que apenas os valores listados estejam na lista.
  2. A solução que eu implementei foi: você pode alterar o tipo de campo da lista Selecionar para o campo de texto, da API do campo e pedir ao Drupal para salvar o valor como está. Agora, no tempo de execução do formulário, você precisará alterar o formulário, alterar o tipo para selecionar a lista e pressionar as opções que desejar. Durante o envio, você precisará atribuir o valor correto exigido pelo campo, que será salvo no banco de dados como está. Certifique-se de que seu manipulador de envio seja chamado antes do manipulador de envio de formulário padrão, para isso você pode usararray_merge

Se a primeira solução funcionar para você, você economizará muito tempo codificando e testando as coisas. MAS, se a lista suspensa for dinâmica e você não tiver controle sobre ela, talvez seja necessário usar a segunda solução.

Poste se você enfrentar algum problema, eu trabalhei bastante nesse problema, no meu projeto, e fiz em ~ 50 formulários, PHEW !!! :)

Vaibhav Jain
fonte
3

Eu encontrei a melhor maneira de contornar isso é definir #valuena lista de seleção.

Se tivermos o valor no formstate e estiver em nossas opções, não receberemos um erro. Se nosso valor não estiver nas opções, selecione a primeira opção em nossas opções e use-a.

$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),
  );
Prumo
fonte
2

Minha solução:

/**
 * 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;
}
Códio
fonte
-1

No seu retorno de chamada ajax, adicione:

...

drupal_get_messages();
form_get_errors();

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

Como medida de precaução, a _form_validate()função principal verifica se a chave #options de um elemento foi alterada em relação ao que foi definido na compilação original (que possui). Ligando drupal_get_messages()e form_get_errors()basicamente dizemos ao Drupal para ignorar quaisquer erros / mensagens enquanto executa nossa solicitação ajax. :)

JC3
fonte
A mensagem de erro desapareceu, mas o elemento select ainda contém a classe de erro. Como remover ou impedir isso?
Tejas Vaidya
Este é o equivalente do Drupal de colocar fita sobre uma luz de aviso no painel de instrumentos do seu veículo.
Frank Robert Anderson