Jak dodać klasę CSS do etykiety formularza?

11

Chcę dodać klasę CSS do etykiety na stronie korzystającej z interfejsu API formularza Drupal 8. Nie udało mi się znaleźć w Internecie informacji o tym, jak to zastosować. Użyłem następującego obejścia, ale daje ono dziwne wyniki.

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

a renderowany HTML to:

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

Instrukcja div nie tylko znajduje się w niewłaściwym miejscu, ale jest renderowana dwukrotnie.

Znalazłem posty sprzed kilku lat, które pokazują, że nie było to możliwe, ale mam nadzieję, że od tego czasu, a wraz z D8, zostało to naprawione. Nie chcę tego robić z prefiksem / sufiksem, ale jako osobny element tablicy.

PS: ta strona to Drupal 8.0.0-rc2

Steve D.
źródło

Odpowiedzi:

11

Wiem, że to stary wątek, ale dla każdego Googling.

Kluczem do tego jest template_preprocess_form_element().

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

#label_attributes jest standardową tablicą atrybutów, więc bardzo łatwo ustawić klasę ['class' => ['my-class', 'other-class']]

#title_display przyjmuje 3 wartości:

  • before: Etykieta jest wyprowadzana przed elementem. To jest domyślne.

  • po: etykieta jest wyprowadzana za elementem. Na przykład jest to używane dla elementów #type radia i pola wyboru.

  • niewidoczne: etykiety mają krytyczne znaczenie dla czytników ekranu, aby umożliwić im prawidłowe poruszanie się po formularzach, ale mogą rozpraszać wzrok. Ta właściwość ukrywa etykietę dla wszystkich oprócz czytników ekranu.
  • atrybut: Ustaw atrybut tytułu na elemencie, aby utworzyć etykietkę narzędzia, ale nie wypisuj elementu etykiety. Jest to obsługiwane tylko w przypadku pól wyboru i radia
mediaashley
źródło
6

Właśnie to sprawdziłem i nie sądzę, aby możliwe było dodanie klasy bezpośrednio do elementu etykiety.

Jak zapewne wiesz, klasy są zwykle dodawane z #attributes w następujący sposób:

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

Jednak właśnie przetestowałem i #attributes nie dodaje klas do elementu Label.

Czy można dodać element formy opakowania, nadać mu klasę, a następnie stylizować etykietę na podstawie faktu, że jest ona elementem potomnym elementu opakowania? Lubię to:

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

Spowoduje to wyświetlenie przykładowego pola tekstowego (i jego etykiety) w elemencie DIV, który ma klasę, tzn. Możesz nadać styl etykiecie:

.your-class label {
  /* your CSS here */
}
Markus Sipilä
źródło
4

Istnieje kilka opcji, aby to zrobić w Drupal> = 8.0.0. Wszystko to naprawdę obraca się wokół nadpisań szablonów w kompozycji, ale moduł powinien być w stanie zaimplementować haki szablonów zdefiniowane przez inne moduły

  1. Najprostszą, ale niedynamiczną opcją jest bezpośrednie zastąpienie form-element-label.html.twig bezpośrednio. Może to działać, jeśli wszystkie etykiety otrzymają form-controlklasę.
  2. Zgodnie z tymi liniami, implementacja template_preprocess_form_element_label pozwoli ci zrobić to samo i dodać form-controlklasę do atrybutów bez przesłonięcia szablonu.
  3. Możesz także zaimplementować szablon_preprocess_form_element i dodać logikę, aby nie zastępować $variables['label'], ale pobierać jego wartości z określonego klucza w tablicy elementów formularza.
mradcliffe
źródło
2

Do przycisków przesyłania możemy dodać klasę jak poniżej:

$ form ['Actions'] ['upload'] ['# atrybuty'] ['class'] [] = 'use-ajax-Submit';

Subhash
źródło
1

Najczystsza opcja, jaką znalazłem, jest zgodna z powyższą sugestią @ mradcliffe. Np. W definicji formularza -

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

Następnie w module niestandardowym zaimplementuj element_hakowania_procesu:

/**
* 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'];
    }
}

Uwaga: zastąpi to wszystkie klasy etykiet, które Drupal chce dodać. W moim przypadku jest w porządku. W razie potrzeby powyższy kod można zmienić, aby temu zapobiec.

Nate
źródło
1

Aby wypełnić odpowiedź @Nate, jeśli chcesz dodać te klasy do istniejącego formularza, możesz to zrobić w 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'];
}

A następnie użyj hook_preprocess_form_element dla pola tekstowego lub hook_preprocess_fieldset dla pola radiowego:

/**
 * 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.
źródło