it-swarm-es.com

Lista de selección dinámica en el formulario (menú desplegable dependiente)

Estoy usando Drupal siete. Quiero hacer que las opciones en una lista de selección dependan del valor elegido en otra lista de selección en un formulario. Estoy seguro de que esto se ha pedido muchas veces antes, pero tengo dificultades para encontrar una respuesta clara sobre cómo hacer esto.

El formulario es para que los usuarios ingresen un historial de trabajo. Necesitan seleccionar un escuadrón que sea una referencia de nodo para el tipo de campo del escuadrón, y esto está en una lista desplegable. Sin embargo, el escuadrón depende de una lista desplegable de la ciudad. Los usuarios primero deben seleccionar una ciudad que luego filtre las opciones para el escuadrón. En el tipo de contenido del escuadrón, creé una taxonomía para la ciudad que se etiqueta al escuadrón.

Estaría muy agradecido por cualquier sugerencia sobre la mejor manera (¿la más simple?) De hacer esto, o por cualquier recurso útil en línea que pueda ayudar.

29
Ben

Puedes usar Ajax para lograr esto. Drupal 7 ahora tiene un buen soporte para Ajax. En su primera lista de selección (ciudad) deberá agregar información de Ajax. Luego, la segunda lista de selección se puede completar en función de la información en la primera También puede ocultar la segunda lista de selección hasta que se seleccione una opción en la primera, y explicaré cómo hacerlo en un momento. Primero, para configurar el formulario básico:

$form['city'] = array(
  '#type' => 'select',
  '#title' => t('City'),
  '#options' => $options,
  '#ajax' => array(
    'event' => 'change',
    'wrapper' => 'squadron-wrapper',
    'callback' => 'mymodule_ajax_callback',
    'method' => 'replace',
  ),
);
$form['squadron_wrapper'] = array('#prefix' => '<div class="squadron-wrapper">', '#suffix' => '</div>');
$form['squadron_wrapper']['squadron'] = array(
  '#type' => 'select',
  '#title' => t('Squadron'),
  '#options' => $squadron_options,
);

Esta es solo la configuración básica de los elementos. Ahora necesitará una manera de determinar qué opciones deben ir en el escuadrón. Primero debe hacer que su devolución de llamada Ajax se identifique en la lista de selección de 'ciudad'. En la mayoría de los casos, puede devolver el elemento que envuelve el elemento ajax, en este caso $ form.

function mymodule_ajax_callback($form, $form_state) {
  return $form;
}

Ahora, cuando la lista de selección 'ciudad' cambie, reconstruirá la parte de envoltura del escuadrón del formulario. Su valor de 'ciudad' ahora estará en $ form_state ['valores']. Entonces, cuando se reconstruye el formulario, necesitamos determinar qué opciones dar a la lista de selección en función del valor de 'ciudad'.

// Get the value of the 'city' field.
$city = isset($form_state['values']['city']) ? $form_state['values']['city'] : 'default';
switch ($city) {
  case 'default':
    // Set default options.
    break;
  case 'losangeles':
    // Set up $squadron_options for los angeles.
    break;
}

// If you want to hide the squadron select list until a city is
// selected then you can do another conditional.
if ($city !== 'default') {
  $form['squadron_wrapper']['squadron'] = array(
    '#type' => 'select',
    '#title' => t('Squadron'),
    '#options' => $squadron_options,
  );
}
27
jordojuice

Muchas gracias a jordojuice arriba. Con su ayuda logré encontrar una solución. También me referí al ejemplo en http://public-action.org/content/drupal-7-form-api-dependent-lists-and-ajax-form-submission . Finalmente utilicé el siguiente código que funcionaba en un módulo personalizado. Por alguna razón, no pude encontrar ninguno de mis valores en los valores $ form_state, pero pude encontrarlos en $ form. Finalmente, cuando probé, recibí un mensaje de error que Drupal había detectado una elección ilegal en el menú desplegable. Obtuve esto al comentar la línea 1290 en form.inc:

form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.'));

El código final que utilicé fue:

<?php

function sappers_squadron_form_work_history_node_form_alter(&$form, &$form_state) {     
        //echo '<pre>';
        //print_r ($form);
        //echo '</pre>';

        $squadron_options = array();

        if(isset($form['field_wkhist_city']['und']['#default_value'][0])) {
            $city = $form['field_wkhist_city']['und']['#default_value'][0];
        }
        else {
            $city = 0;
        }

        $squadron_options = sappers_squadron_squadrons($city);

        $form['field_wkhist_city']['und']['#ajax'] = array(
            'event' => 'change',
            'wrapper' => 'squadron-wrapper',
            'callback' => 'sappers_squadron_ajax_callback',
            'method' => 'replace',
        );

        $form['field_squadron']['und']['#prefix'] = '<div id="squadron-wrapper">';
        $form['field_squadron']['und']['#suffix'] = '</div>';
        $form['field_squadron']['und']['#options'] = $squadron_options;
}


function sappers_squadron_ajax_callback($form, $form_state) {   
    $city = $form['field_wkhist_city']['und']['#value'];

    $form['field_squadron']['und']['#options'] = sappers_squadron_squadrons($city);

    return $form['field_squadron'];
}


function sappers_squadron_squadrons($city) {
    $nodes = array();

    $select = db_query("SELECT node.title AS node_title, node.nid AS nid FROM  {node} node INNER JOIN {taxonomy_index} taxonomy_index ON node.nid = taxonomy_index.nid WHERE (( (node.status = '1') AND (node.type IN  ('squadron')) AND (taxonomy_index.tid = $city) )) ORDER BY node_title ASC");

    $nodes[]="";

    foreach ($select as $node) {
            $nodes[$node->nid] = $node->node_title;
    }

    return $nodes;
}

?>
11
Ben

poner la línea de código, es decir
$nodes[''] = '- None -'; Después

 $nodes = array();

en ur sappers_squadron_squadrons function y eso resolverá su error

form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.'));

2
Hacker

La causa raíz de "Se ha detectado una elección ilegal. Póngase en contacto con el administrador del sitio". es que la cadena vacía con el valor de 0 agregado por $nodes[]=""; no es válido para el campo field_squadron.

Consulte Avance PHP Programación y desarrollo , pero tenga en cuenta que DANGEROUS_SKIP_CHECK y las banderas validadas están en desuso en D7 .

Después de eliminar esa línea, el error desapareció.

1
Siripong

Use el módulo Límite de opción del campo de referencia

Este módulo permite que los campos de referencia de varios tipos tengan las opciones disponibles de sus widgets limitadas por los valores de otros campos en la entidad actual.

0
Rakesh Nimje