web-dev-qa-db-fra.com

Liste de sélection dynamique dans le formulaire (liste déroulante dépendante)

J'utilise Drupal sept. Je veux que les options d'une liste de sélection dépendent de la valeur choisie dans une autre liste de sélection d'un formulaire. Je suis sûr que cela a été demandé plusieurs fois avant, mais j'ai du mal à trouver une réponse claire sur la façon de procéder.

Le formulaire permet aux utilisateurs d'entrer un historique de travail. Ils doivent sélectionner un escadron qui est une référence de nœud au type de champ d'escadron, et cela se trouve dans une liste déroulante. Cependant, l'escadron dépend d'une liste déroulante des villes. Les utilisateurs doivent d'abord sélectionner une ville qui filtrera ensuite les options de l'escadron. Dans le type de contenu de l'escadron, j'ai créé une taxonomie pour la ville qui est étiquetée pour l'escadron.

Je serais très reconnaissant à tous les conseils sur la meilleure façon (la plus simple?) De procéder, ou à toute ressource utile en ligne qui pourrait aider.

29
Ben

Vous pouvez utiliser Ajax pour cela. Drupal 7 a un bon support Ajax maintenant. Sur votre première liste de sélection (ville), vous devrez ajouter des informations Ajax. Ensuite, la deuxième liste de sélection peut être remplie en fonction des informations contenues dans la première . Vous pouvez également masquer la deuxième liste de sélection jusqu'à ce qu'une option de la première soit sélectionnée, et je vais vous expliquer comment procéder dans un instant. Tout d'abord, pour configurer le formulaire de base:

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

Ce n'est que la configuration de base des éléments. Maintenant, vous aurez besoin d'un moyen de déterminer quelles options devraient aller dans l'escadron. Vous devez d'abord faire votre rappel Ajax identifié dans la liste de sélection "ville". Dans la plupart des cas, vous pouvez simplement renvoyer l'élément qui enveloppe l'élément ajax, dans ce cas $ form.

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

Désormais, lorsque la liste de sélection "ville" change, elle reconstruit la partie enveloppe de l'escadron du formulaire. Votre valeur 'city' sera désormais dans $ form_state ['values']. Ainsi, lorsque le formulaire est reconstruit, nous devons déterminer les options à donner à la liste de sélection en fonction de la valeur de "ville".

// 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

Un grand merci à jordojuice ci-dessus. Avec son aide, j'ai réussi à trouver une solution. J'ai également fait référence à l'exemple à http://public-action.org/content/drupal-7-form-api-dependent-lists-and-ajax-form-submission . J'ai finalement utilisé le code ci-dessous qui fonctionnait dans un module personnalisé. Pour une raison quelconque, je n'ai trouvé aucune de mes valeurs dans les valeurs $ form_state, mais j'ai pu les trouver sous $ form. Enfin, lorsque j'ai testé, je recevais un message d'erreur qui Drupal avait détecté un choix illégal dans le menu déroulant. J'ai contourné cela en commentant la ligne 1290 dans form.inc:

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

Le code final que j'ai utilisé était:

<?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

mettre la ligne de code i.e
$nodes[''] = '- None -'; Après

 $nodes = array();

in ur sappers_squadron_squadrons function et cela résoudra votre erreur

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

2
Hacker

La cause première de "Un choix illégal a été détecté. Veuillez contacter l'administrateur du site." est que la chaîne vide avec la valeur 0 ajoutée par $nodes[]=""; n'est pas valide pour le champ field_squadron.

Voir Advance PHP Programmation et développement , mais gardez à l'esprit que DANGEROUS_SKIP_CHECK et les drapeaux validés sont déconseillés dans D7 .

Après avoir supprimé cette ligne, l'erreur a disparu.

1
Siripong

Utilisez le module Limite d'option du champ de référence

Ce module permet aux champs de référence de plusieurs types d'avoir les options disponibles de leurs widgets limitées par les valeurs des autres champs de l'entité actuelle.

0
Rakesh Nimje