Método más sencillo para campos condicionales en un formulario.

20

¿Cuál es la forma más fácil de obtener algo de magia de JavaScript para habilitar / deshabilitar campos de formulario basados ​​en el valor de otro campo? Esto suena como algo que debería haber un ayudante para algún lugar, pero no puedo encontrarlo. Estoy buscando una solución que no esté restringida a los nodos.

Fuzzy76
fuente
No estoy seguro de que esta sea realmente una pregunta de Drupal. Es JavaScript y debe preguntarse en Stack Overflow.
Camsoft
3
Estaba buscando una solución Drupal. Soy capaz de escribir el Javascript para él, pero realmente parece que debería estar conectado a la API de formulario de alguna manera.
Fuzzy76
Eso es genial. No creo que eso estuviera claro en la pregunta original. No conozco ningún módulo que pueda hacer esto.
Camsoft

Respuestas:

18

La magia es usar la propiedad #ahah / #ajax con elementos de formulario, de esa manera puede definir qué debería desencadenar la modificación y qué debería modificarse como resultado, además se integra perfectamente con jQuery.

Esta es la parte importante del siguiente ejemplo:

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

Aquí hay un ejemplo que muestra una página basada en formularios con dos menús desplegables: la lista de opciones en el segundo menú desplegable depende de la selección en el primer menú desplegable.

<?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();
    }
}
picos salvajes
fuente
Esta es la forma correcta de alterar un formulario dependiendo del valor de uno de sus campos. Pero para ocultar / mostrar o habilitar / deshabilitar campos, la propiedad #states en el elemento de formulario es más fácil.
Pierre Buyle
6

¿El módulo de campos condicionales no hace exactamente eso?

Al editar un nodo, los campos controlados se muestran dinámicamente y se ocultan con JavaScript.

Descifrar
fuente
Para formularios de nodo y campos CCK, sí. Pero quería algo que pudiera usarse en otras circunstancias. Aclararé mi pregunta.
Fuzzy76
3

Hay dos sistemas diferentes que puede usar:

  • # ahah / # ajax le permite enviar el formulario con AJAX y reconstruirlo en el lado del servidor. Útil cuando realmente desea agregar nuevos elementos de formulario, el ejemplo típico en D6 es upload.module. Ya explicado anteriormente.
  • Nuevo en Drupal 7 es el sistema #states que le permite hacer cosas como mostrar / ocultar / habilitar / deshabilitar elementos de formulario basados ​​en otros elementos. Consulte http://www.randyfay.com/node/58 para obtener más información al respecto.
Berdir
fuente
1

El método más fácil sería escribir su propio JavaScript y usar jQuery para adjuntar controladores de eventos a los eventos de desenfoque y enfoque. Luego, cuando se activen sus devoluciones de llamada, deshabilite / habilite los campos según su lógica.

Camsoft
fuente
¿Y si no es capaz de escribir su propia jQuery? ¿No sería un módulo Drupal tan fácil como la codificación? - Debido a la aclaración de la pregunta, retracto mi comentario.
Descifrar el
En primer lugar, yo mismo no conocía el módulo de Campos condicionales, en segundo lugar, ¿cuánto gasto adicional agregará un módulo como este a su proyecto sobre algún JS simple del lado del cliente?
Camsoft