¿Cómo agrego una clase CSS a una etiqueta de formulario?

11

Quiero agregar una clase CSS a una etiqueta en una página que usa la API de formularios Drupal 8. No he podido encontrar una referencia en línea sobre cómo aplicar eso. He utilizado la siguiente solución, pero produce algunos resultados extraños.

public function buildForm(array $form, FormStateInterface $form_state)
{
    $form['label1']  = array(
        '#type' => 'label',
        '#title' => $this->t('QUESTIONNAIRE'),
        '#id'         => 'lbl1',
        '#prefix'     => '<div class="caption1">',
        '#suffix'     => '</div>',
    ) ;

y el HTML renderizado es:

<div class="caption1"><label for="lbl1" class="control-label">
<div class="caption1"></div>QUESTIONNAIRE
  </label>

La declaración div no solo está en el lugar equivocado, sino que se representa dos veces.

Había encontrado publicaciones de hace varios años que muestran que esto no era posible, pero espero que desde entonces, y con D8, se haya solucionado. No quiero hacerlo con prefijo / sufijo, sino como un elemento de matriz separado.

PD: este sitio es Drupal 8.0.0-rc2

Steve D.
fuente

Respuestas:

11

Sé que este es un hilo viejo, pero para cualquiera que busque en Google.

La clave de esto está en template_preprocess_form_element().

$element += [
    '#title_display' => 'before',
    '#wrapper_attributes' => [],
    '#label_attributes' => [],
  ];

#label_attributes es una matriz de atributos estándar, por lo que es muy fácil establecer una clase con ['class' => ['my-class', 'other-class']]

#title_display toma 3 valores:

  • before: la etiqueta sale antes del elemento. Este es el valor predeterminado.

  • after: la etiqueta sale después del elemento. Por ejemplo, esto se usa para elementos de radio y casilla de verificación #type.

  • invisible: las etiquetas son críticas para los lectores de pantalla para permitirles navegar adecuadamente a través de los formularios, pero pueden distraer visualmente. Esta propiedad oculta la etiqueta para todos, excepto los lectores de pantalla.
  • atributo: establezca el atributo de título en el elemento para crear una información sobre herramientas pero no generar ningún elemento de etiqueta. Esto solo es compatible con casillas de verificación y radios
mediaashley
fuente
6

Acabo de comprobar esto y no creo que sea posible agregar una clase directamente a un elemento de etiqueta.

Como probablemente sepa, las clases se agregan normalmente con # atributos de la siguiente manera:

 $form['foo'] = array(
  '#type' => 'textfield',
  '#title' => 'Foo',
  '#attributes' => array('class' => array('first-class', 'second-class')),
);

Sin embargo, acabo de probar y #attributes no agrega clases a un elemento Label.

¿Es posible que agregue un elemento de formulario de contenedor, le dé una clase y luego le dé estilo a su etiqueta en función del hecho de que es un elemento secundario del elemento de contenedor? Me gusta esto:

$form['container'] = array(
  '#type' => 'container',
  '#attributes' => array('class' => array('your-class')),
);
$form['container']['foo'] = array(
  '#type' => 'textfield',
  '#title' => 'Foo',
);

Ahora, esto representará el campo de texto de ejemplo (y su etiqueta) dentro de un elemento DIV que tiene su clase, es decir, puede diseñar su etiqueta:

.your-class label {
  /* your CSS here */
}
Markus Sipilä
fuente
4

Hay varias opciones para hacer esto en Drupal> = 8.0.0. Todos estos realmente giran en torno a las anulaciones de plantillas en un tema, pero un módulo debe poder implementar los ganchos de preproceso de plantilla definidos por otros módulos

  1. La opción más simple pero no dinámica es anular directamente form-element-label.html.twig . Esto podría funcionar si todas las etiquetas obtendrán la form-controlclase.
  2. Siguiendo estas líneas, la implementación de template_preprocess_form_element_label le permitiría hacer lo mismo y agregar form-controlclase a los atributos sin anular la plantilla.
  3. También podría implementar template_preprocess_form_element y agregar lógica para no sobrescribir $variables['label'], pero tomar sus valores de alguna clave definida en la matriz de elementos de formulario.
mradcliffe
fuente
2

Para los botones de envío podemos agregar clases como a continuación:

$ form ['actions'] ['submit'] ['# atributos'] ['class'] [] = 'use-ajax-submit';

Subhash
fuente
1

La opción más limpia que encontré es según la sugerencia # 3 de @mradcliffe anterior. Por ejemplo, en su definición de forma:

$form['distance'] = [
        '#type' => 'select',
        '#title' => 'Distance',
        '#required' => true,
        '#options' => [
            '10' => '10 Miles',
            '25' => '25 Miles',
            '50' => '50 Miles',
            '100' => '100 Miles'
        ],
        '#label_classes' => [
            'some-label-class'
        ]
    ];

Luego, en un módulo personalizado, implemente hook_preprocess_form_element:

/**
* Implementation of hook_preprocess_form_element
* @param $variables
*/
function your_module_preprocess_form_element(&$variables)
{
    if(isset($variables['element']['#label_classes'])) {
        $variables['label']['#attributes']['class'] = $variables['element']['#label_classes'];
    }
}

Tenga en cuenta que esto anulará cualquier clase de etiqueta que Drupal quiera agregar. En mi caso eso está bien. El código anterior puede modificarse para evitar esto si es necesario.

Nate
fuente
1

Para completar la respuesta @Nate, si desea agregar estas clases a un formulario existente, puede hacerlo en hook_form_alter:

function your_module_form_alter(&$form, FormStateInterface &$form_state, $form_id)
{
    // for a textfield
    $form['distance']['widget'][0]['value']['#label_classes'] = ['some-label-class'];
    // for a radio field
    $form['country']['widget']['#label_classes'] = ['some-label-class'];
}

Y luego use hook_preprocess_form_element para el campo de texto o hook_preprocess_fieldset para el campo de radio:

/**
 * Implements hook_preprocess_hook().
 */
function your_module_preprocess_fieldset(&$variables)
{
  if(isset($variables['element']['#label_classes'])) {
    foreach ($variables['element']['#label_classes'] as $class) {
      $variables['legend']['attributes']->addClass($class);
    }
  }
}
Marie P
fuente