0

This must be simple, but I cannot find the answer.

I want the label and the textfield on the same line. I tried this:

'odt-filter' => array(
  '#type' => 'textfield',
  '#title' => 'Filtra',
  '#attributes' => array(
    'id' => array(
      'odt-filter',
      ),
    'class' => array(
      'container-inline',
    ),
  ),
) ,

but then the class is applied to the input element, not to the item that contains both it and the label:

<div class="js-form-item form-item js-form-type-textfield form-type-textfield js-form-item-odt-filter form-item-odt-filter">
  <label for="edit-odt-filter">Filtra</label>
  <input id="odt-filter" class="container-inline form-text" data-drupal-selector="edit-odt-filter" name="odt-filter" value="" size="60" maxlength="128" type="text">
</div>

so that the class has not the desired effect. I can (and I actually did, somewhere else) enclose the form element in a container which I can apply the class to, but since a container is already provided by default, I guess there should be a way to add a class to it... isn't there?

1
  • I don't remember if there's already a built-in class or key to achieve what you want. But here's a superb blog article about theming form elements in D8: thirdandgrove.com/theming-form-elements-drupal-8. Alternatively you can simply achieve this with a few lines of CSS.
    – leymannx
    Commented Dec 12, 2018 at 14:25

2 Answers 2

3

The label placement is something set by the theme you're using, and should be consistent across your site. If all labels are above the corresponding element, you should think twice about changing that position just for one or only a few form elements. If you want all the labels next to the element instead of above, the proper place to change that is in the theme.

But let me answer the question as posed:

There is no need to complicate the document structure by adding container elements for the sole purpose of adding a class. The Form API already wraps input elements with a div, and adds standard classes to these divs, so the trick here is to target the existing div and put your class on that existing div.

You can add your class to the div surrounding the form element by using the totally undocumented property #wrapper_attributes. It is used like this:

'odt-filter' => [
  '#type' => 'textfield',
  '#title' => 'Filtra',
  '#wrapper_attributes' => [
    'id' => 'odt-filter',
    'class' => ['container-inline'],
  ],
] ,

Note this is Drupal 8 so I have changed your example to use short array syntax and I have changed your 'id' attribute to be a string, not an array. You may use both the #attributes and the #wrapper_attributes properties at the same time, in case you wanted to add the class to the div and the id to the input, for example.

1

Wrap your element in a container like here:

$form['frame'] = ['#type' => 'container', '#attributes' => ['class' => ['container-inline']]];
$form['frame']['e_mail'] = [
      '#type' => 'email',
      '#title' => $this->t('EMail'),
    ];

For your code it should work like

$form['odt-filter'] = [
      '#type' => "container",
      '#attributes' => ['class' => ['container-inline']],
      'odt-filter' => [
        '#type' => 'textfield',
        '#title' => 'Filtra',
        '#attributes' => [
          'id' => [
            'odt-filter',
          ],
        ],
      ],
    ];
2
  • OP asks how to add a class to an existing container I think. Which would be a task for hook_form_alter, no?
    – leymannx
    Commented Dec 12, 2018 at 19:56
  • Thank you, but I'm afraid you skipped the very last lines of my question :) Iknow that and I did that already, I just wanted to understand if I can reuse the container provided by default... Commented Dec 13, 2018 at 8:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.