web-dev-qa-db-fra.com

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?

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 de sélection, le dernier est 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.

10
Codium

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;
}
2
Codium

--- 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é ..."

15
jaimealsilva

J'ai trouvé le meilleur moyen de contourner ce problème en définissant le #value dans 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),
  );
3
Bob

J'ai rencontré ce problème un certain nombre de fois dans Drupal 6, en changeant 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 aurez pour modifier le formulaire, modifiez le type pour sélectionner la liste et les options Push, 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 utiliser array_merge

Si la première solution fonctionne pour vous, vous économiserez beaucoup de temps sur le codage et les tests. MAIS si la liste dans la liste déroulante 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 !!! :)

3
Vaibhav Jain