Comment éviter «Un choix illégal a été détecté» lors de la mise à jour des valeurs de la liste de sélection via ajax?

10

J'ai quatre champs de référence d'entité pour l'entité utilisateur dans un formulaire. Le formulaire hôte est un formulaire de modification de nœud. Trois d'entre eux sont des listes sélectionnées, le dernier est le formulaire d'entité en ligne .

Après avoir ajouté une entité utilisateur via IEF, j'essaie de mettre à jour les valeurs des listes de sélection:

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

Cela fonctionne, mais lorsque j'essaie d'ajouter un autre utilisateur via IEF, j'obtiens:

Un choix illégal a été détecté. Veuillez contacter l'administrateur du site.

Codium
la source
Est-ce que l'une des Relatedquestions énumérées ici à droite a résolu ce problème?
Jimajamma
@Jimajamma, il semble que la reconstruction du formulaire de rappel ajax ne fonctionne pas. Comment puis-je l'activer? $ form_state ['rebuild'] = TRUE ne fait rien ...
Codium
@Jimajamma donc les solutions connexes ne fonctionnent pas
Codium
J'ai répondu à votre question ici car il s'agit d'une question en double drupal.stackexchange.com/questions/15989/…
Sina Salek

Réponses:

15

--- Réponse originale. Est faux, vérifiez la mise à jour ci-dessous.

Il suffit de régler

$bla['#validated'] = TRUE

Sur la sélection qui sera mise à jour avec AJAX.

Paiement "Un choix illégal a été détecté"

--- Mise à jour 17 décembre 2019 ---

En fait, ce n'était pas un bon conseil, c'était il y a longtemps, maintenant je sais mieux.

La fonction de rappel Ajax est censée renvoyer uniquement le morceau de formulaire qui a changé ou certaines commandes ajax.

Dans ce cas, la modification du formulaire doit être effectuée sur la fonction de formulaire ou sur un crochet de modification de formulaire. Les fonctions de création de formulaire et de validation sont exécutées chaque fois qu'un rappel ajax est appelé. Vérifiez simplement $ form_state sur votre formulaire de création ou de modification de fonction et ajustez les valeurs en conséquence.

Voir Résoudre l'erreur "Un choix illégal a été détecté ..."

jaimealsilva
la source
1
Si je me souviens bien, j'ai essayé cela, sans succès dans mon cas, merci
Codium
1
Je crains que cela ne fonctionne pas non plus pour moi.
kevin.coyle
Cela ne rend-il pas le formulaire moins sécurisé?
Binny
Oui, tous les commentaires précédents sont corrects. La réponse a été mise à jour.
jaimealsilva
3

J'ai rencontré ce problème plusieurs fois dans Drupal 6, modifiant les valeurs de la liste Select via Ajax.

Voici ce que vous pouvez faire

  1. Si possible, essayez d'insérer toutes les valeurs possibles dans l'API de champ, vous devez modifier ce champ, puis lorsque vous modifiez les valeurs, vous devrez vous assurer que seules les valeurs répertoriées figurent dans la liste.
  2. La solution que j'ai implémentée était, vous pouvez changer le type de champ de Select list en textfield, de Field API, et demander à Drupal d'enregistrer la valeur telle quelle. Maintenant, lors de l'exécution du formulaire, vous devrez modifier le formulaire, changer le type pour sélectionner la liste et insérer les options que vous souhaitez. Lors de la soumission également, vous devrez attribuer la valeur correcte requise par le champ, qui sera enregistrée dans la base de données telle quelle. Assurez-vous que votre gestionnaire de soumission est appelé avant le gestionnaire de soumission de formulaire par défaut, pour cela vous pouvez utiliserarray_merge

Si la première solution fonctionne pour vous, vous économiserez beaucoup de temps de codage et de test. MAIS si la liste dans le menu déroulant est dynamique et que vous n'avez aucun contrôle sur elle, vous devrez peut-être opter pour la deuxième solution.

Postez si vous rencontrez des problèmes, j'ai fait beaucoup de travail sur ce problème, pour mon projet, et je l'ai fait pour ~ 50 formulaires, PHEW !!! :)

Vaibhav Jain
la source
3

J'ai trouvé le meilleur moyen de contourner ce problème en définissant le #valuesur la liste de sélection.

Si nous avons la valeur dans formstate et qu'elle est dans nos options, nous n'obtiendrons pas d'erreur. Si notre valeur n'est pas dans les options, sélectionnez la première option dans nos options et utilisez-la.

$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),
  );
Bob
la source
2

Ma solution:

/**
 * 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
la source
-1

Dans votre rappel ajax, ajoutez:

...

drupal_get_messages();
form_get_errors();

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

Par mesure de sécurité, la _form_validate()fonction principale vérifie si la clé #options d'un élément a changé par rapport à ce qui avait été défini dans la version d'origine (ce qu'ils ont). En appelant drupal_get_messages()et form_get_errors()nous disons à Drupal d'ignorer toutes les erreurs / messages lors de l'exécution de notre demande ajax. :)

JC3
la source
Le message d'erreur a disparu mais l'élément select contient toujours la classe d'erreur. Comment supprimer ou empêcher cela?
Tejas Vaidya
C'est l'équivalent Drupal de mettre du ruban adhésif sur un voyant sur le tableau de bord de votre véhicule.
Frank Robert Anderson