Como adiciono uma classe CSS a um rótulo de formulário?

11

Quero adicionar uma classe CSS a um rótulo em uma página que esteja usando a API do Drupal 8 Form. Não consegui encontrar uma referência on-line sobre como aplicar isso. Eu usei a seguinte solução alternativa, mas produz alguns resultados estranhos.

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

e o HTML renderizado é:

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

A declaração div não está apenas no lugar errado, mas é renderizada duas vezes.

Eu encontrei postagens de vários anos atrás que mostram que isso não era possível, mas espero que desde então, e com o D8, isso tenha sido corrigido. Não quero fazer isso com prefixo / sufixo, mas como um elemento de matriz separado.

PS: este site é Drupal 8.0.0-rc2

Steve D.
fonte

Respostas:

11

Eu sei que este é um tópico antigo, mas para qualquer pessoa que esteja pesquisando no Google.

A pista para isso está em template_preprocess_form_element().

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

#label_attributes é uma matriz de atributos padrão, muito fácil de definir uma classe com ['class' => ['my-class', 'other-class']]

#title_display leva 3 valores:

  • antes: o rótulo é emitido antes do elemento. Esse é o padrão.

  • after: O rótulo é produzido após o elemento. Por exemplo, isso é usado para elementos de rádio e caixa de seleção #type.

  • invisível: os rótulos são essenciais para os leitores de tela, para que possam navegar adequadamente pelos formulários, mas podem ser visualmente perturbadores. Esta propriedade oculta o rótulo para todos, exceto os leitores de tela.
  • atributo: defina o atributo title no elemento para criar uma dica de ferramenta, mas não produza nenhum elemento de rótulo. Isso é suportado apenas para caixas de seleção e rádios
mediaashley
fonte
6

Acabei de verificar isso e não acredito que seja possível adicionar uma classe diretamente a um elemento label.

Como você provavelmente sabe, as classes são normalmente adicionadas com # atributos, da seguinte maneira:

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

No entanto, acabei de testar e #attributes não adiciona classes a um elemento Label.

É possível adicionar um elemento de formulário do invólucro, atribuir uma classe a ele e estilizar seu rótulo com base no fato de que ele é filho do elemento do invólucro? Como isso:

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

Agora, isso renderizará o exemplo do campo de texto (e seu rótulo) dentro de um elemento DIV que possui sua classe, ou seja, você pode estilizar seu rótulo:

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

Existem várias opções para fazer isso no Drupal> = 8.0.0. Todos eles realmente giram em torno de substituições de modelo em um tema, mas um módulo deve ser capaz de implementar ganchos de pré-processo de modelo definidos por outros módulos

  1. A opção mais simples, mas não dinâmica, é substituir diretamente o formulário-elemento-rótulo.html.twig . Isso pode funcionar se todos os rótulos receberem a form-controlclasse.
  2. Seguindo essas linhas, a implementação de template_preprocess_form_element_label permitiria que você fizesse a mesma coisa e adicionasse form-controlclasse aos atributos sem substituir o modelo.
  3. Você também pode implementar template_preprocess_form_element e adicionar lógica para não substituir $variables['label'], mas pegar seus valores de alguma chave definida na matriz de elementos do formulário.
mradcliffe
fonte
2

Para botões de envio, podemos adicionar classe como abaixo:

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

Subhash
fonte
1

A opção mais limpa que encontrei é a sugestão nº 3 de @ mradcliffe acima. Por exemplo, na sua definição de formulário -

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

Em um módulo customizado, 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'];
    }
}

Observe que isso substituirá qualquer classe de rótulo que o Drupal queira adicionar. No meu caso, tudo bem. O código acima pode ser alterado para evitar isso, se necessário.

Nate
fonte
1

Para concluir a resposta do @Nate, se você quiser adicionar essas classes a um formulário existente, faça-o em 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'];
}

E, em seguida, use o hook_preprocess_form_element para o campo de texto ou um hook_preprocess_fieldset para o campo de rádio:

/**
 * 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
fonte