Einfachste Methode für bedingte Felder in einem Formular

20

Was ist der einfachste Weg, um JavaScript-Magie zum Aktivieren / Deaktivieren von Formularfeldern basierend auf dem Wert eines anderen Felds zu erlangen? Das hört sich so an, als ob es irgendwo einen Helfer geben sollte, aber ich kann ihn nicht finden. Ich suche eine Lösung, die nicht auf Knoten beschränkt ist.

Fuzzy76
quelle
Ich bin mir nicht sicher, ob dies wirklich eine Drupal-Frage ist. Es ist ein JavaScript und sollte bei Stack Overflow gefragt werden.
Camsoft
3
Ich habe nach einer Drupal-Lösung gesucht. Ich bin in der Lage, das Javascript dafür zu schreiben, aber es fühlt sich wirklich so an, als ob es irgendwie in die Formular-API eingesteckt werden sollte.
Fuzzy76
Das ist cool. Ich denke nicht, dass das in der ursprünglichen Frage klar war. Mir ist kein Modul bekannt, das dies tun könnte.
Camsoft

Antworten:

18

Die Magie verwendet die Eigenschaft #ahah / #ajax mit Formularelementen. Auf diese Weise können Sie definieren, was die Änderung auslösen soll und was als Ergebnis geändert werden soll, und es lässt sich nahtlos in jQuery integrieren.

Dies ist der wichtige Teil aus dem folgenden Beispiel:

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

Das folgende Beispiel zeigt eine formularbasierte Seite mit zwei Dropdown-Listen: Die Liste der Optionen in der zweiten Dropdown-Liste hängt von der Auswahl in der ersten Dropdown-Liste ab.

<?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();
    }
}
Wildpeaks
quelle
Dies ist der richtige Weg, um ein Formular abhängig vom Wert eines seiner Felder zu ändern. Das Ausblenden / Anzeigen oder Aktivieren / Deaktivieren von Feldern ist mit der Eigenschaft #states für das Formularelement einfacher.
Pierre Buyle
6

Tut das Modul Bedingte Felder nicht genau das?

Beim Bearbeiten eines Knotens werden die kontrollierten Felder mit JavaScript dynamisch angezeigt und ausgeblendet.

Entziffern
quelle
Ja, für Knotenformulare und CCK-Felder. Aber ich wollte etwas, das unter anderen Umständen verwendet werden könnte. Ich werde meine Frage klären.
Fuzzy76
3

Es gibt zwei verschiedene Systeme, die Sie verwenden können:

  • Mit # ahah / # ajax können Sie das Formular mit AJAX senden und auf dem Server neu erstellen. Nützlich, wenn Sie tatsächlich neue Formularelemente hinzufügen möchten. Ein typisches Beispiel in D6 ist upload.module. Bereits oben erklärt.
  • Neu in Drupal 7 ist das #States-System, mit dem Sie Dinge wie das Anzeigen / Verbergen / Aktivieren / Deaktivieren von Formularelementen basierend auf anderen Elementen ausführen können. Weitere Informationen hierzu finden Sie unter http://www.randyfay.com/node/58 .
Berdir
quelle
1

Die einfachste Methode wäre, Ihr eigenes JavaScript zu schreiben und mit jQuery Event-Handler an die Unschärfe- und Fokusereignisse anzuhängen. Wenn Ihre Rückrufe ausgelöst werden, deaktivieren / aktivieren Sie die Felder entsprechend Ihrer Logik.

Camsoft
quelle
Und wenn er nicht in der Lage ist, seine eigene jQuery zu schreiben? Wäre ein Drupal-Modul nicht einfacher als das Codieren? - Aufgrund der Klärung der Frage widerrufe ich meinen Kommentar.
entziffern
Erstens war mir das Modul Bedingte Felder selbst nicht bekannt. Zweitens, wie viel Overhead wird ein solches Modul seinem Projekt über ein einfaches clientseitiges JS hinzufügen?
Camsoft