¿Cómo evitar "Se ha detectado una elección ilegal" al actualizar los valores de la lista de selección a través de ajax?

10

Tengo cuatro campos de referencia de entidad para entidad de usuario en un formulario. El formulario de host es un formulario de edición de nodo. Tres de ellos son listas seleccionadas, el último es el formulario de entidad en línea .

Después de agregar una entidad de usuario a través de IEF, estoy tratando de actualizar los valores de las listas de selección:

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, pero cuando intento agregar otro usuario a través de IEF obtengo:

Se ha detectado una elección ilegal. Por favor contacte al administrador del sitio.

Codium
fuente
¿Alguna de las Relatedpreguntas aquí enumeradas a la derecha resolvió esto?
Jimajamma
@Jimajamma parece que en la devolución de llamada ajax la reconstrucción no funciona. ¿Cómo puedo habilitarlo? $ form_state ['rebuild'] = VERDADERO no hacer nada ...
Codium
@Jimajamma para que las soluciones relacionadas no funcionen
Codium
He respondido su pregunta aquí porque es una pregunta duplicada drupal.stackexchange.com/questions/15989/…
Sina Salek

Respuestas:

15

--- Respuesta original. Está mal, verifique la actualización a continuación.

Solo establece

$bla['#validated'] = TRUE

En la selección que se actualizará con AJAX.

Comprobación "Se ha detectado una elección ilegal"

--- Actualización 17 dic 2019 ---

En realidad no fue un buen consejo, eso fue hace mucho tiempo, ahora lo sé mejor.

Se supone que la función de devolución de llamada Ajax solo devuelve la parte de la forma que ha cambiado o algunos comandos ajax.

En este caso, la modificación del formulario debe realizarse en la función de formulario o en un enlace de alteración de formulario. Las funciones de creación y validación de formularios se ejecutan cada vez que se llama una devolución de llamada ajax. Simplemente marque $ form_state en su formulario de compilación o altere la función y ajuste los valores en consecuencia.

Consulte Resolver el error "Se ha detectado una elección ilegal ..."

jaimealsilva
fuente
1
Si recuerdo bien, intenté esto, sin éxito en mi caso, gracias
Codium
1
Me temo que esto tampoco funciona para mí.
kevin.coyle
¿Esto no hace que el formulario sea menos seguro?
Binny
Sí, todos los comentarios anteriores son correctos. La respuesta ha sido actualizada.
jaimealsilva
3

Me he enfrentado a este problema varias veces en Drupal 6, cambiando los valores de la lista Seleccionar a través de Ajax.

Esto es lo que puedes hacer es

  1. Si es posible, intente insertar todos los valores posibles en la API de campo, debe editar ese campo y, cuando cambie los valores, tendrá que asegurarse de que solo los valores enumerados estén en la lista.
  2. La solución que implementé fue: puede cambiar el tipo de campo de Seleccionar lista a campo de texto, de API de campo y pedirle a Drupal que guarde el valor como está. Ahora, en el tiempo de ejecución del formulario, deberá modificar el formulario, cambiar el tipo para seleccionar la lista e insertar las opciones que desee. Durante el envío también, deberá asignar el valor correcto requerido por el campo, que se guardará en la base de datos tal como está. Asegúrese de que se llama a su controlador de envío antes del controlador de envío de formulario predeterminado, para eso puede usararray_merge

Si la primera solución funciona para usted, ahorrará mucho tiempo codificando y probando cosas. PERO si la lista en el menú desplegable es dinámica y no tiene control sobre ella, es posible que deba elegir una segunda solución.

Publica si tienes problemas, he trabajado bastante en este problema para mi proyecto, y lo hice para ~ 50 formularios, ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ :)

Vaibhav Jain
fuente
3

He encontrado la mejor manera de evitar esto es establecer el #valueen la lista de selección.

Si tenemos el valor en formstate y está en nuestras opciones, no obtendremos un error. Si nuestro valor no está en las opciones, seleccione la primera opción en nuestras opciones y úsela.

$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),
  );
Beto
fuente
2

Mi solución:

/**
 * 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
fuente
-1

En su devolución de llamada ajax, agregue:

...

drupal_get_messages();
form_get_errors();

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

Como precaución de seguridad, la _form_validate()función principal verifica si la clave #options de un elemento ha cambiado de lo que se configuró en la compilación original (que tienen). Al llamar drupal_get_messages()y form_get_errors()básicamente le decimos a Drupal que ignore cualquier error / mensaje mientras ejecuta nuestra solicitud ajax. :)

JC3
fuente
El mensaje de error desapareció pero el elemento de selección aún contiene la clase de error. ¿Cómo eliminarlo o evitarlo?
Tejas Vaidya
Este es el equivalente de Drupal de colocar cinta adhesiva sobre una luz de advertencia en el tablero de instrumentos de su vehículo.
Frank Robert Anderson el