> For the complete documentation index, see [llms.txt](https://analog.groupthought.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://analog.groupthought.com/reference/alpine/predictive-search.md).

# x-predictive-search

Directives and a magic for Shopify's predictive search API: a live search form, section-rendered results, and a combobox options list.

Directives and a magic for Shopify's predictive search API: a live search form, section-rendered results, and a combobox options list.

| Directive / magic                  | What it does                                                                                                                                                       |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `x-predictive-search="section-id"` | The root. Holds the query, state, and result HTML. The expression names the theme section that renders results (required)                                          |
| `x-predictive-search:form`         | The search form. Its `resources[*]` fields are included in every request. Submitting cancels any pending request                                                   |
| `x-predictive-search:input`        | The search input. Two-way bound to the query; searches 350ms after typing stops                                                                                    |
| `x-predictive-search:results`      | Receives the returned section HTML (`x-html`)                                                                                                                      |
| `x-predictive-search:options`      | The list of result links inside the results section                                                                                                                |
| `x-predictive-search:option`       | One result link                                                                                                                                                    |
| `$predictiveSearch`                | The state, readable anywhere inside the root: `state` (`'idle'` \| `'loading'` \| `'error'` \| `'success'`), `error`, `query`, `resultHtml`, `search()`, `reset()` |

The input gets `role="combobox"`, `aria-autocomplete="list"`, `aria-controls`, and `aria-owns`. The options element becomes a listbox with roving tabindex. Each option gets `role="option"`. ArrowDown from the input focuses the first option; ArrowUp focuses the last. The plugin doesn't add a live region. Add a `role="status"` element bound to `$predictiveSearch.state` to announce loading.

Requests go to `routes.predictive_search_url` with the query, the section id, and the form's `resources[*]` fields (type, limit, limit\_scope, and options). Fields outside that set stay out of the request.

## Examples

### A basic search form

Use `x-predictive-search:form` and `x-predictive-search:input` inside a root that names the results section:

```html
<div x-data x-predictive-search="predictive-search-results">
  <form action="{{ routes.search_url }}" x-predictive-search:form>
    <input type="hidden" name="resources[type]" value="product" />
    <input name="q" type="search" x-predictive-search:input placeholder="Search" />
    <button type="submit">Search</button>
  </form>
  <div x-show="$predictiveSearch.state != 'idle'">
    <div x-predictive-search:results></div>
  </div>
</div>
```

The plugin sets the input's `id` itself, so a visible label binds with `:for="$id('predictive-search-input')"`.

### The results section

Use `x-predictive-search:options` and `x-predictive-search:option` in the section the root names, rendering from the `predictive_search` Liquid object:

```liquid
{% if predictive_search.performed %}
  <ul x-predictive-search:options>
    {% for result in predictive_search.resources.products %}
      <li role="presentation">
        <a href="{{ result.url }}" x-predictive-search:option>{{ result.title }}</a>
      </li>
    {% endfor %}
  </ul>
{% endif %}
```

Analog's `predictive-search-results` section renders queries, products, pages, articles, and collections this way, each link marked `x-predictive-search:option`.

### Showing search state

Use `$predictiveSearch.state` to show progress, and a `role="status"` element to announce it:

```html
<div
  class="sr-only"
  role="status"
  x-text="$predictiveSearch.state == 'loading' ? 'Searching' : ''"
></div>
<div x-show="$predictiveSearch.resultHtml == null">
  {% render 'predictive-search-suggestions' %}
</div>
```

The flyout shows suggested searches while `resultHtml` is null and swaps to results once a search succeeds.

### Resetting when the flyout closes

Use `$predictiveSearch.reset()` to clear the query and results when the surface that holds the search goes away:

```html
<div
  x-predictive-search="predictive-search-results"
  x-effect="
    if (!$popover.isOpen) {
      $predictiveSearch.reset()
    }
  "
>
  …
</div>
```

The root also resets itself whenever the query becomes an empty string, so clearing the input wipes the results without extra code.

## Options

| Option         | What it does                                                                                                                             |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| The expression | The id of the section that renders results (required). The response is that section's HTML, rendered with the `predictive_search` object |

See [Search](/features/search.md) for the header flyout, Menu drawer search, and suggested searches.
