Méthode la plus simple pour les champs conditionnels dans un formulaire


20

Quel est le moyen le plus simple d'obtenir de la magie javascript pour activer / désactiver les champs de formulaire en fonction de la valeur d'un autre champ? Cela ressemble à quelque chose, il devrait y avoir un assistant quelque part, mais je ne le trouve pas. Je recherche une solution qui ne se limite pas aux nœuds.


Pas sûr que ce soit vraiment une question Drupal. C'est un code JavaScript et devrait être demandé sur Stack Overflow.
Camsoft

3
Je cherchais une solution Drupal. Je suis capable d'écrire le Javascript pour cela, mais j'ai vraiment l'impression qu'il devrait être connecté à l'API Form d'une manière ou d'une autre.
Fuzzy76

C'est super. Je ne pense pas que c'était clair dans la question initiale. Je ne connais aucun module qui pourrait le faire.
Camsoft

Réponses:


18

La magie consiste à utiliser la propriété #ahah / #ajax avec des éléments de formulaire, de cette façon, vous pouvez définir ce qui doit déclencher la modification et ce qui doit être modifié en conséquence, en plus il s'intègre parfaitement avec jQuery.

C'est la partie importante de l'exemple ci-dessous:

'#ajax' => array(
    'event' => 'change',
    'callback' => 'myajax_ajax_callback',
    'wrapper' => 'dropdown_second_replace',
),

Voici un exemple qui montre une page basée sur un formulaire avec deux listes déroulantes: la liste des options dans la deuxième liste déroulante dépend de la sélection dans la première liste déroulante.

<?php

/**
 * Implementation of hook_menu().
 * Registers a form-based page that you can access at "http://localhost/myajax"
 */
function myajax_menu(){
    return array(
        'myajax' => array(
            'title' => 'A page to test ajax',
            'page callback' => 'drupal_get_form',
            'page arguments' => array('myajax_page'),
            'access arguments' => array('access content'), 
        )
    );
}



/**
 * A form with a dropdown whose options are dependent on a
 * choice made in a previous dropdown.
 *
 * On changing the first dropdown, the options in the second are updated.
 */
function myajax_page($form, &$form_state) {
    // Get the list of options to populate the first dropdown.
    $options_first = myajax_first_dropdown_options();

    // If we have a value for the first dropdown from $form_state['values'] we use
    // this both as the default value for the first dropdown and also as a
    // parameter to pass to the function that retrieves the options for the
    // second dropdown.
    $value_dropdown_first = isset($form_state['values']['dropdown_first']) ? $form_state['values']['dropdown_first'] : key($options_first);

    $form['dropdown_first'] = array(
        '#type' => 'select',
        '#title' => 'First Dropdown',
        '#options' => $options_first,
        '#default_value' => $value_dropdown_first,

        // Bind an ajax callback to the change event (which is the default for the
        // select form type) of the first dropdown. It will replace the second
        // dropdown when rebuilt
        '#ajax' => array(
            // When 'event' occurs, Drupal will perform an ajax request in the
            // background. Usually the default value is sufficient (eg. change for
            // select elements), but valid values include any jQuery event,
            // most notably 'mousedown', 'blur', and 'submit'.
            'event' => 'change',
            'callback' => 'myajax_ajax_callback',
            'wrapper' => 'dropdown_second_replace',
        ),
    );
    $form['dropdown_second'] = array(
        '#type' => 'select',
        '#title' => 'Second Dropdown',
        // The entire enclosing div created here gets replaced when dropdown_first
        // is changed.
        '#prefix' => '<div id="dropdown_second_replace">',
        '#suffix' => '</div>',
        // when the form is rebuilt during ajax processing, the $value_dropdown_first variable
        // will now have the new value and so the options will change
        '#options' => myajax_second_dropdown_options($value_dropdown_first),
        '#default_value' => isset($form_state['values']['dropdown_second']) ? $form_state['values']['dropdown_second'] : '',
    );
    return $form;
}

/**
 * Selects just the second dropdown to be returned for re-rendering
 *
 * Since the controlling logic for populating the form is in the form builder
 * function, all we do here is select the element and return it to be updated.
 *
 * @return renderable array (the second dropdown)
 */
function myajax_ajax_callback($form, $form_state) {
    return $form['dropdown_second'];
}


/**
 * Helper function to populate the first dropdown. This would normally be
 * pulling data from the database.
 *
 * @return array of options
 */
function myajax_first_dropdown_options() {
    return array(
        'colors' => 'Names of colors',
        'cities' => 'Names of cities',
        'animals' => 'Names of animals',
    );
}


/**
 * Helper function to populate the second dropdown. This would normally be
 * pulling data from the database.
 *
 * @param key. This will determine which set of options is returned.
 *
 * @return array of options
 */
function myajax_second_dropdown_options($key = '') {
    $options = array(
        'colors' => array(
            'red' => 'Red',
            'green' => 'Green',
            'blue' => 'Blue'
        ),
        'cities' => array(
            'paris' => 'Paris, France',
            'tokyo' => 'Tokyo, Japan',
            'newyork' => 'New York, US'
        ),
        'animals' => array(
            'dog' => 'Dog',
            'cat' => 'Cat',
            'bird' => 'Bird'
        ),  
    );
    if (isset($options[$key])) {
        return $options[$key];
    }
    else {
        return array();
    }
}

C'est la bonne façon de modifier un formulaire en fonction de la valeur de l'un de ses champs. Mais pour masquer / afficher ou activer / désactiver des champs, la propriété #states sur l'élément de formulaire est plus facile.
Pierre Buyle

6

Le module Champs conditionnels ne fait-il pas exactement cela?

Lors de la modification d'un nœud, les champs contrôlés sont affichés et masqués dynamiquement avec JavaScript.


Pour les formulaires de nœuds et les champs CCK, oui. Mais je voulais quelque chose qui pourrait être utilisé dans d'autres circonstances. Je vais clarifier ma question.
Fuzzy76

3

Il existe deux systèmes différents que vous pouvez utiliser:

  • # ahah / # ajax vous permet de soumettre le formulaire avec AJAX et de le reconstruire côté serveur. Utile lorsque vous souhaitez réellement ajouter de nouveaux éléments de formulaire, l'exemple typique de D6 est upload.module. Déjà expliqué ci-dessus.
  • Nouveau dans Drupal 7 est le système #states qui vous permet de faire des choses comme afficher / masquer / activer / désactiver des éléments de formulaire basés sur d'autres éléments. Voir http://www.randyfay.com/node/58 pour plus d'informations à ce sujet.

1

La méthode la plus simple serait d'écrire votre propre JavaScript et d'utiliser jQuery pour attacher des gestionnaires d'événements aux événements de flou et de focus. Ensuite, lorsque vos rappels sont déclenchés, désactivez / activez les champs en fonction de votre logique.


Et s'il n'est pas capable d'écrire son propre jQuery? Un module Drupal ne serait-il pas facile à coder? - En raison de la clarification de la question, je retire mon commentaire.
Déchiffrez

Premièrement, je n'étais pas au courant du module Champs conditionnels moi-même, deuxièmement, combien de frais généraux un module comme celui-ci ajouterait-il à son projet par rapport à un simple JS côté client?
Camsoft
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.