Najłatwiejsza metoda dla pól warunkowych w formularzu

20

Jaki jest najłatwiejszy sposób na uzyskanie magii javascript do włączania / wyłączania pól formularza na podstawie wartości innego pola? To brzmi jak coś, gdzie powinien być pomocnik, ale nie mogę tego znaleźć. Szukam rozwiązania, które nie jest ograniczone do węzłów.

Fuzzy76
źródło
Nie jestem pewien, czy to naprawdę pytanie Drupala. Jest to JavaScript i należy go zapytać w przypadku przepełnienia stosu.
Camsoft,
3
Szukałem rozwiązania Drupal. Jestem w stanie napisać dla niego JavaScript, ale naprawdę wydaje mi się, że powinien być jakoś podłączony do Form API.
Fuzzy76,
To super. Nie sądzę, by było to jasne w pierwotnym pytaniu. Nie znam żadnego modułu, który mógłby to zrobić.
Camsoft,

Odpowiedzi:

18

Magia polega na użyciu właściwości #ahah / #ajax z elementami formularza, w ten sposób możesz zdefiniować, co powinno wywołać modyfikację, a co powinno zostać zmodyfikowane, a także bezproblemowo integruje się z jQuery.

Jest to ważna część z poniższego przykładu:

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

Oto przykład, który pokazuje stronę opartą na formularzu z dwoma listami rozwijanymi: lista opcji w drugim menu rozwijanym zależy od wyboru w pierwszym menu rozwijanym.

<?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();
    }
}
dzikie piki
źródło
To jest właściwy sposób na zmianę formularza w zależności od wartości jednego z jego pól. Ale aby ukryć / pokazać lub włączyć / wyłączyć pola, właściwość #states w elemencie formularza jest łatwiejsza.
Pierre Buyle,
6

Czy moduł pól warunkowych właśnie tego nie robi?

Podczas edycji węzła kontrolowane pola są dynamicznie pokazywane i ukryte za pomocą JavaScript.

Odszyfrować
źródło
W przypadku formularzy węzłów i pól CCK tak. Chciałem jednak czegoś, co można by wykorzystać w innych okolicznościach. Wyjaśnię moje pytanie.
Fuzzy76
3

Istnieją dwa różne systemy, których możesz użyć:

  • # ahah / # ajax umożliwia przesłanie formularza za pomocą AJAX i przebudowanie go po stronie serwera. Przydatny, gdy naprawdę chcesz dodać nowe elementy formularza, typowym przykładem w D6 jest upload.module. Wyjaśniono już powyżej.
  • Nowością w Drupal 7 jest system #states, który pozwala robić takie rzeczy, jak pokazywanie / ukrywanie / włączanie / wyłączanie elementów formularza na podstawie innych elementów. Więcej informacji na ten temat można znaleźć na stronie http://www.randyfay.com/node/58 .
Berdir
źródło
1

Najłatwiejszą metodą byłoby napisanie własnego kodu JavaScript i użycie jQuery do dołączenia programów obsługi zdarzeń do zdarzeń rozmycia i fokusa. Następnie po uruchomieniu oddzwaniania wyłącz / włącz pola w oparciu o logikę.

Camsoft
źródło
A jeśli nie jest w stanie napisać własnego jQuery? Czy moduł Drupal nie byłby łatwy niż kodowanie? - Ze względu na wyjaśnienie pytania wycofuję swój komentarz.
Odszyfruj
Po pierwsze, sam nie wiedziałem o module pól warunkowych, po drugie, ile narzutu ten moduł doda do swojego projektu w porównaniu z prostym JS po stronie klienta?
Camsoft,