Comment ajouter une classe CSS à une étiquette de formulaire?

11

Je souhaite ajouter une classe CSS à une étiquette sur une page qui utilise l'API Drupal 8 Form. Je n'ai pas pu trouver de référence en ligne sur la façon de l'appliquer. J'ai utilisé la solution de contournement suivante, mais cela produit des résultats étranges.

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>',
    ) ;

et le HTML rendu est:

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

Non seulement l'instruction div est au mauvais endroit, mais elle est rendue deux fois.

J'avais trouvé des messages d'il y a plusieurs années qui montrent que cela n'était pas possible, mais j'espère que depuis, et avec D8, il a été corrigé. Je ne veux pas le faire avec préfixe / suffixe, mais comme élément de tableau séparé.

PS: ce site est Drupal 8.0.0-rc2

Steve D.
la source

Réponses:

11

Je sais que c'est un vieux fil, mais pour quiconque google.

L'indice est là template_preprocess_form_element().

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

#label_attributes est un tableau d'attributs standard, il est donc très facile de définir une classe avec ['class' => ['my-class', 'other-class']]

#title_display prend 3 valeurs:

  • before: l'étiquette est sortie avant l'élément. C'est la valeur par défaut.

  • after: L'étiquette est sortie après l'élément. Par exemple, ceci est utilisé pour les éléments radio et case à cocher #type.

  • invisible: les étiquettes sont essentielles pour que les lecteurs d'écran leur permettent de naviguer correctement dans les formulaires, mais peuvent être gênantes visuellement. Cette propriété masque l'étiquette pour tout le monde sauf les lecteurs d'écran.
  • attribut: définissez l'attribut title sur l'élément pour créer une info-bulle, mais ne produisez aucun élément d'étiquette. Ceci est pris en charge uniquement pour les cases à cocher et les radios
mediaashley
la source
6

Je viens de vérifier cela et je ne pense pas qu'il soit possible d'ajouter une classe directement à un élément label.

Comme vous le savez probablement, les classes sont normalement ajoutées avec #attributes comme suit:

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

Cependant, je viens de tester et #attributes n'ajoute pas de classes à un élément Label.

Est-il possible pour vous d'ajouter un élément de formulaire wrapper, de lui donner une classe, puis de styliser votre étiquette en fonction du fait qu'il s'agit d'un enfant de l'élément wrapper? Comme ça:

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

Maintenant, cela rendra l'exemple de champ de texte (et son étiquette) à l'intérieur d'un élément DIV qui a votre classe, c'est-à-dire que vous pouvez styliser votre étiquette:

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

Il existe plusieurs options pour ce faire dans Drupal> = 8.0.0. Tout cela tourne vraiment autour des remplacements de modèles dans un thème, mais un module devrait être capable d' implémenter des crochets de prétraitement de modèles définis par d'autres modules

  1. L'option la plus simple mais non dynamique consiste à remplacer directement form-element-label.html.twig . Cela pourrait fonctionner si toutes les étiquettes obtiennent la form-controlclasse.
  2. En suivant ces lignes, l'implémentation de template_preprocess_form_element_label vous permettrait de faire la même chose et d'ajouter de la form-controlclasse aux attributs sans redéfinir le modèle.
  3. Vous pouvez également implémenter template_preprocess_form_element et ajouter de la logique pour ne pas écraser $variables['label'], mais prendre ses valeurs dans une clé définie du tableau d'éléments de formulaire.
mradcliffe
la source
2

Pour les boutons de soumission, nous pouvons ajouter une classe comme ci-dessous:

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

Subhash
la source
1

L'option la plus propre que j'ai trouvée est conforme à la suggestion n ° 3 de @ mradcliffe ci-dessus. Par exemple, dans votre définition de formulaire -

$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'
        ]
    ];

Ensuite, dans un module personnalisé, implémentez 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'];
    }
}

Notez que cela remplacera toutes les classes d'étiquettes que Drupal souhaite ajouter. Dans mon cas, ça va. Le code ci-dessus peut être modifié pour éviter cela si nécessaire.

Nate
la source
1

Pour compléter la réponse @Nate, si vous souhaitez ajouter ces classes à un formulaire existant, vous pouvez le faire dans 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'];
}

Et puis utilisez le hook_preprocess_form_element pour le champ de texte ou un hook_preprocess_fieldset pour le champ 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
la source