
The following OOP hook goes into the same class as the formAlter() method we defined above. By changing the input element to a button we can then inject a small SVG of a magnifying glass or similar to act as the search button.The first step (and perhaps the trickiest) is to alter the search form to add a couple of attributes to the search submit element.In this article I will look at how we can use a combination of form alters and suggestion hooks to change the Search API form submit input to a button so that an SVG can be embedded inside.<button{{ attributes }}>
<svg width="20" height=20 viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16.4999 16.5L12.0354 12.0355" stroke="#211E1E" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M8.5 13.5C11.2614 13.5 13.5 11.2614 13.5 8.5C13.5 5.73858 11.2614 3.5 8.5 3.5C5.73858 3.5 3.5 5.73858 3.5 8.5C3.5 11.2614 5.73858 13.5 8.5 13.5Z" stroke="#211E1E" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
An alternative mechanism to using the form ID might be to look at the action of the form, which is normally “/search” for the Search API system. For example, we could rewrite the hook like this.namespace DrupalmymoduleHook;
use DrupalCoreHookAttributeHook;
use DrupalCoreFormFormStateInterface;
use DrupalCoreStringTranslationStringTranslationTrait;
class SearchFormHooks {
use StringTranslationTrait;
public const SEARCH_VIEW_NAME = 'content-search';
/**
* Implements hook_form_alter().
*/
#[Hook('form_alter')]
public function formAlter(&$form, FormStateInterface $form_state, $form_id) {
if ($form_id === 'views_exposed_form' && $form['#id'] === 'views-exposed-form-' . self::SEARCH_VIEW_NAME . '-search-page') {
// Convert the search input to a button.
$form['actions']['submit']['#attributes']['data-twig-suggestion'] = 'search_results_submit';
$form['actions']['submit']['#attributes']['class'][] = 'search-box__button';
$form['actions']['submit']['#attributes']['aria-label'][] = $this->t("Search");
}
}
}
The simplest mechanism to alter the correct form is just to use the name of the view in the hook. For example, if the view was called “content_search” then the form #id element would have the ID “views-exposed-form-content-search-search-page”. We can use this information to alter the form in the following way (using the new OOP hooks mechanism).The template for the input element can be added, which is basically the following code./**
* Implements hook_theme_suggestions_HOOK_alter().
*/
#[Hook('theme_suggestions_input_alter')]
public function themeHookSuggestion(&$suggestions, array $variables) {
$element = $variables['element'];
// Mainly used to swap the search input to a button.
if (isset($element['#attributes']['data-twig-suggestion'])) {
$suggestions[] = 'input__' . $element['#type'] . '__' . $element['#attributes']['data-twig-suggestion'];
}
}
The suggestion hook for the input element can now be focused to look for the data-twig-suggestion attribute in the attributes array. If this is present then we know that we have injected this and can use this in our suggestion. Instead of throwing the attribute away, we pass this along to the suggestion. This gives us the ability to tweak the suggestion based on values in the future if we need to.A common request I see when theming Search API forms is to swap out the normal submit element with a magnifying glass icon. Performing this action isn’t difficult, but it does require adding a couple of operations to add a suggestion so a custom template can be used.Swapping out this input element takes a couple of steps, and I although I have done this technique a few times I still need to dig into old code to figure out how I did it. So, I thought I would document it so I didn’t have to go looking for the solution again.Finding the correct form is a little tricky because the name of the search form differs between sites and is dependent on the view that has been set up to wrap the search results. I normally use the name of the view to do find the right form, but it is also possible to infer the correct form through other means.The search input element should now contain a data attribute called data-twig-suggestion.If we add a theme suggestion alter hook for the input element, the element itself has no knowledge of the context that surrounds it. This makes it tricky to know that we are altering the correct element or even to inject a suggestion that would be unique for the search form.
Adding The Suggestions Hook And Template
The form alter hook, therefore, is used to inject an attribute into the form element so that we can read this in the suggestions hook. This gives is a bit of data we can identify and use in the suggestions hook.With all this in place we now have a button instead of a input element for the search form. That button contains an inline SVG of a magnifying glass and can be further modified to add other text or elements.When I set up a view to perform a search against a Search API index I normally create an exposed filter for the text content. Views shows this as a block that can be embedded into the site. The block, however, comes with a input element to act as the search button, and it isn’t possible to inject SVG icons into input elements.I have thought about releasing this as a contributed module, but the search form detection and the resulting template tend to differ quite a bit from site to site.if ($form_id === 'views_exposed_form' && $form['#action'] === '/search') {
// Convert the search input to a button.
$form['actions']['submit']['#attributes']['data-twig-suggestion'] = 'search_results_submit';
$form['actions']['submit']['#attributes']['class'][] = 'search-box__button';
$form['actions']['submit']['#attributes']['aria-label'][] = t("Search");
}
With that in place we can add our template suggestion hook.<input data-twig-suggestion="search_results_submit" class="search-box__button button js-form-submit form-submit" aria-label="Search" data-drupal-selector="edit-submit-content-search" type="submit" id="edit-submit-content-search" value="Search">
Notice that we also inject a custom class and a aria-label attribute. The class is for general theming purposes, but the aria-label is critical for screen readers. What we are doing here is removing the label of the search and replacing it with an SVG icon. We therefore need to add this label to ensure that screen readers will still identify the button with the correct label.



