¿Cómo puedo desactivar una única casilla de verificación en un elemento FAPI 'casillas de verificación'?

31

El título básicamente lo dice todo, quiero deshabilitar una sola casilla de verificación de un elemento de tipo de casilla de verificación FAPI.

No quiero hacerlo con JavaScript, ni cambiarlo de casillas de verificación a múltiples elementos de casilla de verificación es una opción ya que el elemento lo proporciona otro módulo.

Pensamientos?

Descifrar
fuente
Hay un error tipográfico en su pregunta: "desactivar"
FR6

Respuestas:

36

¡Existe una forma limpia en Drupal 7! Aparentemente, según esta publicación , aún no está documentado.

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  $form['checkboxes_element']['#disabled'] = TRUE; //disables all options
  $form['checkboxes_element'][abc]['#disabled'] = TRUE; //disables option, called abc
}

Otro ejemplo .

También puede establecer la función #access en FALSE, para ocultar completamente la casilla de verificación.

timofey.com
fuente
3
Con el error tipográfico corregido, este código me funciona absolutamente en D7. ¡Gracias!
beth
1
Gran captura! Gustoso de trabajar para ti.
timofey.com
2
Si usa #access, entonces si la casilla de verificación está establecida en #default_values, no se establecerá en los valores de estado de formulario al enviar.
Nick
Esto funciona muy bien.
David Meister
No funcionará con casillas de verificación (puede seleccionar más de un elemento) usando Mejores filtros expuestos (BEF) en vistas, AFAICT.
1kenthomas
22

Desafortunadamente, no hay una forma realmente limpia de hacerlo en FAPI. Su mejor opción , si está decidido, es alterar una función #proceso adicional en el elemento de casillas de verificación.

La función predeterminada agregada a los elementos del tipo 'casillas de verificación' es en realidad una función ( expand_checkboxes () ) divide el elemento individual en múltiples elementos del tipo 'casilla de verificación' que luego se fusionan en uno. Si tuviera que aprovechar su segunda función de proceso, podría alcanzar el grupo expandido de elementos de 'casilla de verificación' y desactivar el en cuestión.

El siguiente código no se ha probado por completo, por lo que se recomienda:

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  $form['checkboxes_element']['#process'][] = 'mymodule_disable_element';
}

function mymodule_disable_element($element) {
  foreach (element_children($element) as $key) {
    if ($key == YOUR_CHECK_VALUE) {
      $element[$key]['#disabled'] = TRUE;
      return;
    }
  }
}
Eaton
fuente
Suena mejor que el enfoque que tomé, que consistía en adjuntar una función de tema al elemento y ejecutar un preg_replace()sobre el resultado.
Descifrar
Puede agregar un "descanso"; dentro de la declaración if anterior para un poco más de eficiencia, a menos que espere ver la misma clave de elemento dos veces.
Chris Cohen
Buena captura, Chris, cambié el fragmento de código. ¡Gracias!
Eaton
2
La respuesta aceptada parece un poco exagerada en comparación con la respuesta de @ timofey.
Citricguy
6

Aquí está mi código para Drupal 7, para cambiar el elemento Roles en la página Editar usuario.

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  $form['checkboxes_element']['#pre_render'][] = 'form_process_checkboxes'; // I had to add this one, or it will return the first role only with my callback bellow
  $form['checkboxes_element']['#pre_render'][] = 'mymodule_disable_element';
}

function mymodule_disable_element(($element) {
  foreach (element_children($element) as $key) {
    if ($key == YOUR_CHECK_VALUE) {
      $element[$key]['#attributes']['disabled'] = 'disabled';
    }
  }
  return $element;
}
aFeijo
fuente
3

Estoy usando casillas de verificación como "asignar" y "desasignar". El cliente me ha pedido que desactive "desasignar", pero aún es importante representar "asignación". Teniendo en cuenta que las casillas de verificación DESACTIVADAS se envían como "falsas" y, si no se manejan correctamente, se desasignarán, divido mis casillas de verificación en "procesarlas" e "ignorar estas deshabilitadas". Así es cómo:

// Provide LIVE checkboxes only for un-assigned Partners
$form['partner']['partners'] = array(
  '#type' => 'checkboxes',
  '#options' => array_diff($partners, $assignments),
  '#title' => t($partnername),
);
// Provide DISABLED checkboxes for assigned Partners (but with a different variable, so it doesn't get processed as un-assignment)
$form['partner']['partner_assignments'] = array(
  '#type' => 'checkboxes',
  '#options' => $assignments,
  '#default_value' => array_keys($assignments),
  '#disabled' => TRUE,
  '#title' => t($partnername),
);

Tenga en cuenta que 'partner_assignments' es su propia matriz / variable y no se procesará como "unassign", en mi caso de uso. Gracias por publicar, me llevó a esta solución.

texas-bronius
fuente
3

D7 Aquí teníamos que asegurarnos de que al agregar un nodo, una determinada opción de referencia de término de taxonomía siempre no se puede marcar y siempre se guardará en el nodo. Así que entramos en #after_build y deshabilitamos esa determinada opción, pero tuvimos que asegurarnos de que al final esa opción se pasará. Porque solo deshabilitarlo habría detenido el viaje de esa opción a ganchos futuros.

// a constant
define('MYTERM', 113);

/**
 * Implements hook_form_alter().
 */
function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
    if ($form_id == 'MYCONTENTTYPE_node_form') {
    $form['#after_build'][] = 'MYMODULE_MYCONTENTTYPE_node_form_after_build';
    }
}

/**
 * Implements custom after_build_function()
 */
function MYMODULE_MYCONTENTTYPE_node_form_after_build($form, &$form_state) {
  foreach (element_children($form['field_MYFIELD'][LANGUAGE_NONE]) as $tid) {
    if ($tid == MYTERM) {
      $element = &$form['field_MYFIELD'][LANGUAGE_NONE][$tid];
      $element['#checked'] = TRUE;
      $element['#attributes']['disabled'] = 'disabled';
    }
  }
  // here's ensured the term's travel goes on
  $form['field_MYFIELD'][LANGUAGE_NONE]['#value'] += drupal_map_assoc(array(MYTERM));
  return $form;
}

Así es como se ve la opción deshabilitada:

ingrese la descripción de la imagen aquí

leymannx
fuente
2

No pude obtener la respuesta de Eaton para que funcione tal como está escrita (la devolución de llamada #process no devuelve nada, y se llama antes de que se expandan las casillas de verificación) y también quería que el valor regresara de la casilla de verificación deshabilitada (quería que estuviera marcada permanentemente ) Esto funcionó para mí (D6).

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  $form['checkboxes_element']['#process'][] = 'mymodule_disable_element';
}

function mymodule_disable_element($element) {
  $expanded = expand_checkboxes($element);
  $checkbox =& $expanded[YOUR_CHECK_VALUE];
  $checkbox['#disabled'] = TRUE;
  $checkbox['#value_callback'] = 'mymodule_element_value_callback';
  return $expanded;
}

function mymodule_element_value_callback($element, $edit = FALSE) {
  // Return whatever value you'd like here, otherwise the element will return
  // FALSE because it's disabled.
  return 'VALUE';
}

Si alguien conoce una forma más ordenada, ¡me encantaría escucharla!

Andy
fuente
Fatal error: Call to undefined function expand_checkboxes()
leymannx
1
@koivo Esta fue una respuesta D6, la función ya no existe en D7
Andy
1

Aquí está mi código para Drupal 7, para cambiar el elemento Roles en la página Editar usuario.

function mymodule_form_alter(&$form, &$form_state, $form_id) {
  $form['checkboxes_element']['#pre_render'][] = 'form_process_checkboxes'; // I had to add this one, or it will return the first role only with my callback bellow
  $form['checkboxes_element']['#pre_render'][] = 'mymodule_disable_element';
}

function mymodule_disable_element(($element) {
  foreach (element_children($element) as $key) {
    if ($key == YOUR_CHECK_VALUE) {
      $element[$key]['#attributes']['disabled'] = 'disabled';
      return $element;
    }
  }
  return $element;
}
jrockowitz
fuente
1

En Drupal 7, para deshabilitar las opciones en una selección en una entidad de campo, descubrí que tenía que instalar una #processfunción. Desafortunadamente, esto deshabilitó la función de proceso incorporada, form_process_checkboxespor lo que es necesario volver a agregarla (o llamarla desde su función de proceso). Además, al deshabilitar las casillas de verificación que ya están marcadas, descubrí que el valor incorporado callback ( form_type_checkboxes_value) ignora los valores predeterminados al recuperar resultados de la entrada.

$field_lang_form = &$your_form[$field][LANGUAGE_NONE];
$field_lang_form['#process'][] = 'form_process_checkboxes';
$field_lang_form['#process'][] = 'YOURMODULE_YOURFUNCTION_process';
$field_lang_form['#value_callback'] = 'YOURMODULE_form_type_checkboxes_value';

Entonces algo como esto:

function YOURMODULE_YOURFUNCTION_process($element) {
  // Disallow access YOUR REASON, but show as disabled if option is set.
  foreach (element_children($element) as $field) {
    if (REASON TO DISABLE HERE) {
      if (!empty($element[$field]['#default_value'])) {
        $element[$field]['#disabled'] = TRUE;
      } else {
        $element[$club]['#access'] = FALSE;
      }
    }
  }
  return $element;
}

Y finalmente:

function YOURMODULE_form_type_checkboxes_value($element, $input = FALSE) {
  if ($input !== FALSE) {
    foreach ($element['#default_value'] as $value) {
      if (THIS OPTION WAS SET AND DISABLED - YOUR BUSINESS LOGIC) {
        // This option was disabled and was not returned by the browser. Set it manually.
        $input[$value] = $value;
      }
    }
  }
  return form_type_checkboxes_value($element, $input);
}

No encontré que ninguna de las otras respuestas en esta página funcionó en este caso.

Dan Chadwick
fuente
1

Aquí está mi ejemplo (usando #after_build):

$form['legal']['legal_accept']['#type'] = 'checkboxes';
$form['legal']['legal_accept']['#options'] = $options;
$form['legal']['legal_accept']['#after_build'][] = '_process_checkboxes';

Además de la siguiente devolución de llamada de función:

function _process_checkboxes($element) {
  foreach (element_children($element) as $key) {
    if ($key == 0) { // value of your checkbox, 0, 1, etc.
      $element[$key]['#attributes'] = array('disabled' => 'disabled');
      // $element[$key]['#theme'] = 'hidden'; // hide completely
    }
  }
  return $element;
}

Probado en Drupal 6, pero también debería funcionar para Drupal 7.


Drupal 6

Puede usar la siguiente función ( fuente ):

/*
 * Change options for individual checkbox or radio field in the form
 * You can use this function using form_alter hook.
 * i.e. _set_checkbox_option('field_tier_level', 'associate', array('#disabled' => 'disabled'), $form);
 *
 * @param $field_name (string)
 *    Name of the field in the form
 * @param $checkbox_name (string)
 *    Name of checkbox to change options (if it's null, set to all)
 * @param $options (array)
 *    Custom options to set
 * @param $form (array)
 *    Form to change
 *
 * @author kenorb at gmail.com
 */
function _set_checkbox_option($field_name, $checkbox_name = NULL, $options, &$form) {
    if (isset($form[$field_name]) && is_array($form[$field_name])) {
        foreach ($form[$field_name] as $key => $value) {
            if (isset($form[$field_name][$key]['#type'])) {
                $curr_arr = &$form[$field_name][$key]; // set array as current
                $type = $form[$field_name][$key]['#type'];
                break;
            }
        }
        if (isset($curr_arr) && is_array($curr_arr['#default_value'])) {
            switch ($type) { // changed type from plural to singular
                case 'radios':
                    $type = 'radio';
                    break;
                case 'checkboxes':
                    $type = 'checkbox';
                    break;
            }

            foreach ($curr_arr['#default_value'] as $key => $value) {
                foreach($curr_arr as $old_key => $old_value) { // copy existing options for to current option
                    $new_options[$old_key] = $old_value;
                }
                $new_options['#type'] = $type;  // set type
                $new_options['#title'] = $value;  // set correct title of option
                $curr_arr[$key] = $new_options; // set new options

                if (empty($checkbox_name) || strcasecmp($checkbox_name, $value) == 0) { // check name or set for 
                    foreach($options as $new_key => $new_value) {
                        $curr_arr[$key][$new_key] = $value;
                    }
                }
            }
            unset($curr_arr['#options']); // delete old options settings
        } else {
            return NULL;
        }
    } else {
        return NULL;
    }
}

/*
 * Disable selected field in the form(whatever if it's textfield, checkbox or radio)
 * You can use this function using form_alter hook.
 * i.e. _disable_field('title', $form);
 *
 * @param $field_name (string)
 *    Name of the field in the form
 * @param $form (array)
 *    Form to change
 *
 * @author kenorb at gmail.com
 */
function _disable_field($field_name, &$form) {
    $keyname = '#disabled';

    if (!isset($form[$field_name])) { // case: if field doesn't exists, put keyname in the main array
        $form[$keyname] = TRUE;
    } else if (!isset($form[$field_name]['#type']) && is_array($form[$field_name])) { // case: if type not exist, find type from inside of array
        foreach ($form[$field_name] as $key => $value) {
            if (isset($form[$field_name][$key]['#type'])) {
                $curr_arr = &$form[$field_name][$key]; // set array as current
                break;
            }
        }
    } else {
        $curr_arr = &$form[$field_name]; // set field array as current
    }

    // set the value
    if (isset($curr_arr['#type'])) {
        switch ($curr_arr['#type']) {
            case 'textfield':
            default:
                $curr_arr[$keyname] = TRUE;
        }
    }
}
kenorb
fuente
D7: Lo mismo aquí, usar #after_build funciona como se desea. También confirmando la configuración deshabilitada usando #attribute.
SGhosh
0

Estoy usando el siguiente código en drupal 6: -

$form['statuses'] = array(
    '#type' => 'checkboxes',
    '#options' => $statuses,
    '#default_value' => $status_val,
    '#after_build' => array('legal_process_checkboxes')
    );

y la función de devolución de llamada está aquí: -

/ ** * Procesar cada casilla de verificación basada en 'feture' ya está siendo utilizada por un Subdominio o no. * @param Array $ element array de casillas de verificación de formulario * /

function legal_process_checkboxes($element) {

  foreach (element_children($element) as $key) {

    $feature_id = $key;
    $res_total = '';

    $total = feature_used($feature_id) ;

    if ($total) {
      $element[$key]['#attributes'] = array('disabled' => 'disabled');
    }
  }
  return $element;
}
Sandip Ghosh
fuente
¡Bienvenido a drupal.stackexchange.com! Por favor arregle el formato de su código. Los comentarios antes de la función legal_process_checkboxes () se han dejado fuera del formato "código". Gracias.
ermannob
0

Una cosa importante a tener en cuenta es que las casillas de verificación deshabilitadas no se envían, por lo que es posible que también deba forzar #valuela casilla de verificación. Por ejemplo:

$element['child1']['#disabled'] = TRUE;
$element['child1']['#value'] = 'child1';

En mi caso, sin esto, $form_state['values']no contenía el valor de mi casilla de verificación (que estaba habilitado de forma predeterminada, pero deshabilitado).

Mella
fuente
0

Enganche el campo de texto y cree un cuadro de texto dinámico con información de la base de datos

1 ° obtener la asociación. matriz de la base de datos, por ejemplo

$blah = array('test1' => 'Choose for test1', 'test2' => 'Choose for test2', ...)

2 ° Implementos hook_form_alter()

/ ** * Implementa hook_form_alter (). * id de formulario = vistas-expuestas-formulario * /

function test_form_alter(&$form, &$form_state, $form_id)
{
  //only for this particular form
  if ($form['#id'] == "views-exposed-form-advanced-search-page-2")
    {
       $form['phases'] = array(
           '#type' => 'checkboxes',
           '#options' => $blah,
      );
    }
}

¡3 ° campos múltiples serán verificables!

Mathieu Dierckx
fuente
0

Si está creando su propio formulario, en lugar de ejecutar funciones separadas de form_alter / # process / # pre_render, puede cambiar de 'casillas de verificación' a generar elementos 'checkbox' individuales.

$options = array(
   1 => t('Option one'),
   2 => t('Option two'),
);

// Standard 'checkboxes' method:
$form['my_element'] = array(
  '#type' => 'checkboxes',
  '#title' => t('Some checkboxes'),
  '#options' => $options,
);

// Individual 'checkbox' method:
$form['my_element'] = array(
  '#type' => 'container',
  '#attributes' => array('class' => array('form-checkboxes')),
  '#tree' => TRUE,
  'label' => array('#markup' => '<label>' . t('Some checkboxes') . '</label>',
);
foreach ($options as $key => $label) {
  $form['my_element'][$key] = array(
    '#type' => 'checkbox',
    '#title' => $label,
    '#return_value' => $key,
  );
}
// Set whatever #disabled (etc) properties you need.
$form['my_element'][1]['#disabled'] = TRUE;

'#tree' => TRUEle da la misma estructura de árbol que la versión de casillas de verificación cuando la matriz $ form_state ['values'] llega a la validación / envío / reconstrucción. Si no puede o no quiere usar #tree por alguna razón, asigne a cada casilla de verificación una '#parents' => array('my_element', $key)propiedad para establecer explícitamente su posición en la estructura de valores.

KingAndy
fuente