Как добавить класс CSS в метку формы?

11

Я хочу добавить класс CSS к метке на странице, которая использует Drupal 8 Form API. Мне не удалось найти в Интернете ссылку о том, как это применить. Я использовал следующий обходной путь, но он дает некоторые странные результаты.

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

и представленный HTML-код:

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

Мало того, что выражение div находится не в том месте, оно выводится дважды.

Несколько лет назад я обнаружил сообщения, показывающие, что это невозможно, но я надеюсь, что с тех пор и с D8 это было исправлено. Я не хочу делать это с префиксом / суффиксом, а как отдельный элемент массива.

PS: это сайт Drupal 8.0.0-rc2

Стив Д.
источник

Ответы:

11

Я знаю, что это старая ветка, но для всех Google.

Ключ к этому находится в template_preprocess_form_element().

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

#label_attributes является стандартным массивом атрибутов, поэтому очень легко установить класс с ['class' => ['my-class', 'other-class']]

#title_display принимает 3 значения:

  • before: метка выводится перед элементом. Это по умолчанию.

  • after: метка выводится после элемента. Например, это используется для элементов radio и checkbox #type.

  • невидимый: ярлыки имеют решающее значение для программ чтения с экрана, чтобы они могли правильно перемещаться по формам, но могут отвлекать визуально. Это свойство скрывает метку для всех, кроме программ чтения с экрана.
  • Атрибут: Установите атрибут заголовка для элемента, чтобы создать всплывающую подсказку, но не выводите элемент метки. Это поддерживается только для флажков и радио
mediaashley
источник
6

Я только что проверил это, и я не верю, что возможно добавить класс непосредственно к элементу метки.

Как вы, скорее всего, знаете, классы обычно добавляются с #attributes следующим образом:

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

Однако я только что протестировал, и #attributes не добавляет классы к элементу Label.

Можно ли добавить элемент формы-обертки, присвоить ему класс, а затем стилизовать ярлык на основе того факта, что он является дочерним элементом элемента-обертки? Нравится:

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

Теперь, это будет визуализировать пример текстового поля (и его метку) внутри элемента DIV, который имеет ваш класс, т.е. вы можете стилизовать свою метку:

.your-class label {
  /* your CSS here */
}
Маркус Сипиля
источник
4

Есть несколько вариантов сделать это в Drupal> = 8.0.0. Все они действительно вращаются вокруг переопределений шаблонов в теме, но модуль должен иметь возможность реализовывать хуки предварительной обработки шаблона, определенные другими модулями.

  1. Самый простой, но не динамический вариант - переопределить form-element-label.html.twig напрямую. Это может сработать, если все метки получат form-controlкласс.
  2. Следуя этим правилам, реализация template_preprocess_form_element_label позволит вам сделать то же самое и добавить form-controlкласс к атрибутам без переопределения шаблона.
  3. Вы также можете реализовать template_preprocess_form_element и добавить логику, чтобы не перезаписывать $variables['label'], а получать значения из некоторого определенного ключа в массиве элементов формы.
mradcliffe
источник
2

Для кнопок отправки мы можем добавить класс, как показано ниже:

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

Subhash
источник
1

Самый чистый вариант, который я нашел, соответствует предложению @ mradcliffe №3 выше. Например, в вашем определении формы -

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

Затем в пользовательском модуле реализуем 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'];
    }
}

Обратите внимание, что это переопределит все классы меток, которые Drupal хочет добавить. В моем случае это нормально. Код выше может быть изменен, чтобы предотвратить это при необходимости.

Nate
источник
1

Чтобы завершить ответ @Nate, если вы хотите добавить эти классы в существующую форму, вы можете сделать это в 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'];
}

А затем используйте hook_preprocess_form_element для текстового поля или hook_preprocess_fieldset для радиополя:

/**
 * 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);
    }
  }
}
Мари П
источник