I wonder how I can add a class to the form tag (of the _search_content_ view's) exposed form using template_preprocess_views_exposed_form() (or even better template_preprocess_views_exposed_form__search_content()). The form is exposed as block.

It works so far using the following code in MY_THEME.theme:

function MY_THEME_preprocess_form(&$variables) {
  if ($variables['element']['#form_id'] == 'views_exposed_form' && $variables['element']['#view_id'] == 'search_content') {
    $variables['attributes']['class'][] = 'row';

But I can't get it work for:

function MY_THEME_preprocess_views_exposed_form__search_content(&$variables) {
  // I tried:
  // $variables['attributes']['class'][] = 'does-not-work';

  // and also:
  // $variables['attributes'] = new Attribute($variables['attributes']);
  // $variables['attributes']->addClass('does-not-work');

  // and also manipulating $variables['form'], but this didn't work either.

The function gets called, but it's not adding the class to the form tag. Is it possible to get it work with template_preprocess_views_exposed_form()?

Screenshot of kint($variables) output, for each function:

enter image description here

Is it possible to get it work with template_preprocess_views_exposed_form()?

  • Did you debug the code to see if the array is being modified and the structure is correct?
    – Kevin
    Commented Dec 5, 2018 at 3:32
  • Use hook_form_alter, and ksm, kint, dpm from devel module for debugging.
    – svetlio
    Commented Dec 5, 2018 at 8:45
  • I was using kint(). The array got modified, but the structure of the variables array in MY_THEME_preprocess_form() is different to the one in MY_THEME_preprocess_views_exposed_form__search_content().
    – LarS
    Commented Dec 5, 2018 at 14:08
  • I don't see how hook_form_alter may help, as the preprocessing happens later. I also have MY_THEME_form_views_exposed_form_alter() successfully implemented to modify other parts of the form, but was not able to set the class for the form tag either. – I can set a wrapper via #prefix/suffix with the row class, but it's not what I want, as it would wrap around the form tag, I need the class added to the form tag (or as a container inside the form tag, containing all form elements).
    – LarS
    Commented Dec 5, 2018 at 14:37
  • 1
    Thanks @StefanosPetrakis, I followed your advice and removed the addition.
    – LarS
    Commented Dec 9, 2018 at 23:40

3 Answers 3


Short version: You cannot use hook_preprocess_views_exposed_form() to modify the <form> tag. The <form> tag is independently rendered by a form theme hook set through the #theme_wrappers render property. Which means that it is completely disassociated from the actual views_exposed_form theme hook that renders the (internal) content of the views exposed form.

Long version:

  1. views_theme() defines the views_exposed_form theme hook as returning a form render element. That means that it will eventually be using (unless somehow overridden) the definition provided by the Form render element. If you take a look at that, you will see that that definition sets the'#theme_wrappers' property to ['form']. No surprises so far. :-)
  2. At some point during the theming of a views page (or block), the theme hook views_view comes into play; this theme hook contains the exposed render variable that is essentially the exposed form you are interested in. The render array of exposed holds the following two relevant properties:

    • #theme => views_exposed_form (and other more specific ones like views_exposed_form__search_content): This is the theme hook that will provide the content of the form, i.e. everything inside the <form> tag. This is what you get access to and given the option to modify when calling template_preprocess_views_exposed_form(). This theme hook is not responsible for rendering the <form> tag and does not allow you to change it.
    • #theme_wrappers => ['form'] : This is the #theme_wrappers list of theme hooks; form will provide the actual <form> tag. It will essentially enclose the markup generated by the #theme theme hook into a <form> tag. This is what you get access to when calling template_preprocess_form(). This theme is responsible for rendering the <form> tag and does allow you to change it.

Implementation suggestion

If you would rather let hook_form_alter() implementations handle form-related logic, you could still use another preprocess hook to implement the functionality you want, namely the preprocess_views_view() hook.

function MY_THEME_preprocess_views_view(&$variables) {
  if ($variables['id'] === 'search_content') {
    $variables['exposed']['#attributes']['class'][] = 'row';

Good luck, this is a really good question!

  • Yes, this is quite annoying that you can't form_alter ALL forms (regardless of theme) and set an attribute on the <form> tag. I have been trying to add novalidate attr to get rid of silly HTML5 form validation. I thought adding it with form_alter had worked as it does disable validation. Wasn't until a11y testing that we realized this was only added to wrapper <section> and that this was not allowed (even though it works). Solution at least for the site theme was simply to override form.html.tiwg and add it there. But sadly this is only for the site theme.
    – liquidcms
    Commented Jun 2, 2022 at 18:40

If you want just add Class to form tag to the exposed filter you can do it with hook_form_FORM_ID_alter no need to template_preprocess_views_exposed_form() or template_preprocess_views_exposed_form__search_content() Like the following:

use Drupal\Component\Utility\Html;
 * Implements hook_form_FORM_ID_alter().
function myModuleName_form_views_exposed_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  $form['#attributes']['class'][] = Html::cleanCssIdentifier('your-new-class');
  • 1
    are you sure about that? I tested it and it got added to an outer div. I am wondering if the case is a bit special: The exposed form is shown as drupal block, the class got added to the block's div.
    – LarS
    Commented Dec 8, 2018 at 5:01
  • I am not only interested in a solution, I primarily would like to understand the difference between template_preprocess_views_exposed_form() and template_preprocess_views_exposed_form__search_content() … I am going to point that out in the question.
    – LarS
    Commented Dec 8, 2018 at 5:03

It is because the hook fired for the exposed form is actually 'form' as you can see in the below screenshot:
enter image description here

And this is why it is always a good idea to enable twig debug
Hope that helps!

To elaborate more:
The views exposed form preprocess function does not edit the form itself because this is a different hook. The proper way to add a class to the form is to alter the form it self or use https://api.drupal.org/api/drupal/core%21includes%21form.inc/function/template_preprocess_form/8.6.x because this function is the responsible for adding attributes to the form itself. Also check the twig source of https://api.drupal.org/api/drupal/core%21themes%21stable%21templates%21form%21form.html.twig/8.6.x You'll see that the attributes are printed there.

  • Sorry, I did not yet understand your answer, may I ask you to elaborate a bit more? I am not looking for a hook, instead using the template preprocess functions. If I got it right, they follow the template suggestions, as the twig templates do, like the general one views-exposed-form.html.twig or a more specific one views-exposed-form--search_content.html.twig
    – LarS
    Commented Dec 8, 2018 at 5:10
  • I have twig debugging enabled, but I guess its output is not complete in this situation, as there is no information about FILE NAME SUGGESTIONS, but I know that I can use different templates here, like views-exposed-form.html.twig or the one I am using for the form views-exposed-form--search_content.html.twig.
    – LarS
    Commented Dec 8, 2018 at 5:17
  • Please take a look at the views exposed form twig template here api.drupal.org/api/drupal/… What I understood from your question is that you want to add a class to the form. According to the template you can't. The prints the form with no alterations Commented Dec 8, 2018 at 7:27
  • It works in MY_THEME_preprocess_form(), as stated in the question, but if I got you right it does not matter it's the wrong place, I should not do that?
    – LarS
    Commented Dec 8, 2018 at 19:46
  • No. preprocess_form is the right place if you want to edit the form tag and it is ok to use it. preprocess_views_exposed_form and preprocess_views_ecposed_form__search_content are used to change attributes of the wrapper element around the exposed form and you should not use them if you want to add classes to the form tag for example Commented Dec 9, 2018 at 7:48

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.