Drupal 11: Theming The Search API Search Input
在对搜索 API 表单进行主题化时,我常见的一个需求是用放大镜图标替换普通的提交元素。执行此操作并不困难,但确实需要添加一些操作来添加一个建议,以便可以使用自定义模板。
当我设置一个视图以针对搜索 API 索引执行搜索时,我通常会为文本内容创建一个公开过滤器。视图将其显示为一个可以嵌入到网站中的块。然而,该块带有一个输入元素作为搜索按钮,并且无法将 SVG 图标注入到输入元素中。
通过将输入元素更改为按钮,我们就可以注入一个小的放大镜 SVG 或类似的图标来作为搜索按钮。
替换这个输入元素需要几个步骤,尽管我已经多次使用过这种技术,但我仍然需要翻找旧代码来弄清楚我是如何实现的。所以,我想把它记录下来,这样我就不用再去寻找解决方案了。
在本文中,我将探讨如何结合使用表单修改和建议钩子,将搜索 API 表单的提交输入更改为按钮,以便可以在其中嵌入 SVG。
一、修改搜索表单
第一步(也许是最棘手的一步)是修改搜索表单,为搜索提交元素添加一些属性。
如果我们为输入元素添加一个主题建议修改钩子,该元素本身并不知道围绕它的上下文。这使得很难确定我们正在修改的是正确的元素,甚至难以注入一个对搜索表单唯一的建议。
因此,表单修改钩子用于向表单元素注入一个属性,以便我们可以在建议钩子中读取该属性。这为我们提供了一些可以识别的数据,并在建议钩子中使用。
找到正确的表单有点棘手,因为搜索表单的名称在不同的网站之间有所不同,并且取决于用于包装搜索结果的视图。我通常使用视图的名称来找到正确的表单,但也可以通过其他方式推断出正确的表单。
修改正确表单的最简单机制是在钩子中使用视图的名称。例如,如果视图名为 "content_search",那么表单 #id 元素的 ID 将是 "views-exposed-form-content-search-search-page"。我们可以使用这些信息以以下方式修改表单(使用新的面向对象编程(OOP)钩子机制)。
namespace Drupal\mymodule\Hook;
use Drupal\Core\Hook\Attribute\Hook;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
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");
}
}
}
视图的名称已作为常量添加,以帮助将此钩子移植到其他网站(或搜索表单)。
搜索输入元素现在应该包含一个名为 data-twig-suggestion 的数据属性。
<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">
请注意,我们还注入了一个自定义类和一个 aria-label 属性。该类用于一般的主题化目的,但 aria-label 对于屏幕阅读器至关重要。我们在这里所做的是移除搜索的标签,并用 SVG 图标替换它。因此,我们需要添加这个标签,以确保屏幕阅读器仍然能够将按钮识别为具有正确的标签。
另一种使用表单 ID 的替代机制可能是查看表单的动作,对于搜索 API 系统,该动作通常是 "/search"。例如,我们可以像这样重写钩子。
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");
}
如果上述步骤没有产生结果,你可能需要在你的设置上进行一些实验。
完成这些后,我们可以添加模板建议钩子。
二、添加建议钩子和模板
现在,输入元素的建议钩子可以专注于查找属性数组中的 data-twig-suggestion 属性。如果该属性存在,我们就知道是我们注入的,并且可以在建议中使用它。我们不会丢弃该属性,而是将其传递给建议。这使我们能够在将来根据需要根据值调整建议。
以下面向对象编程(OOP)钩子与我们上面定义的 formAlter() 方法放在同一个类中。
/**
* 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'];
}
}
这将为模板创建一个名为 input--submit--search-results-submit.html.twig 的建议,我们可以将其添加到我们的主题中。
可以添加输入元素的模板,基本上类似于以下代码。
{% set attributes = attributes.setAttribute('aria-label', 'Search'|trans) %}
<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>
虽然没有这些属性表单也能正常工作,但最好还是包含它们,特别是因为我们在表单修改钩子中为搜索添加了 aria-label,并且需要显示该标签。
完成所有这些后,我们现在在搜索表单中使用按钮而不是输入元素。该按钮包含一个内联的放大镜 SVG,并且可以进一步修改以添加其他文本或元素。
我曾考虑将其作为一个贡献模块发布,但搜索表单的检测和最终的模板在不同的网站之间差异很大。

