Frontend Setup

With the content available in the indexes, we now need to be able to actually search and display the results. We're just going to look at a simple keyword search in these examples, but all the same concepts extend to much more complex search setups.

TLDR; Grab the completed markup →

QuickJump:


0. Understanding the Flow

Before you start implementing the front-end, it's important to understand how this will be setup, and why.

When searching, we never hit the actual Craft install or server directly. All actual search queries go direct to the algolia services. This has massive performance benefits, and lets up build a search experience that's unbeatable.

To enable this, all searches are triggered directly via javascript requests, then the returning results are parsed and output on the page. Algolia will return the search results in a nicely formatted array of result objects, and it's up to us on page, to parse these and output our own wrapping markup. We have a number of javascript libraries to help us in this.

What about non-JS Fallbacks? Algolia does support direct searches via RESTful requests. While this isn't currently implemented in SearchPlus, get in touch if you need this option


1. Add Search Form and Markup Containers

Lets look at our most basic search. Just a simple keyword search. For that, we need just a single input, and this follows a completely standard markup :

A. Search Input

<input type="search" name="keywords" placeholder="Search.." id="search-input"/>

Completely standard. The only key thing here, is we have some way to reference this input later to trigger the search activity. Here we've got an id of 'search-input', but that can be anything at all.

B. Search Credentials

As well as the search input, we need to supply our algolia application id, and search api key, along with the index name we want to search. To keep things as portable and clean as possible in our javascript, we can define those as data attributes on the search form. Like so :

<form id="searchform"
         data-applicationId="{{ craft.searchPlus.applicationId }}"
         data-searchApiKey="{{ craft.searchPlus.searchApiKey }}"
         data-index="{{ craft.searchPlus.index('demo_products') }}">
    <input type="search" name="keywords" placeholder="Search.." value="" id="searchinput">
</form>

Here we've set the index name to be demo_products but you'd have that as whatever you've setup internally for your site.

C. Results Containers

Also, it'd be helpful to have a few empty containers in place to later target with out results output.

<div id="results"></div>
<div id="pagination"></div>

2. Setup our Result Markup

Result markup is more interesting. Because the results are coming in via the external search, and not direct from Craft, we can't use a standard Craft/Twig markup to set things up. Instead we can use something very similar, called Hogan. Hogan is simply a javascript templating setup, and it's very similar in appearance and behaviour to Twig.

Hogan markup is simple, the same double braces are used for variables. If your fields might have markup as part of their value and in Craft you'd used a | raw filter, the same is output by triple braces.

A. Results Template

Here's our simple results template :

{% raw %}
    <!-- Hit template -->
    <script type="text/template" id="hit-template">
    <ul>
        {{#hits}}
        <li>
            <h3><a href="{{ uri }}">{{ title }}</a></h3>
            {{{ summary }}}
        </li>
        {{/hits}}
    </ul>
    </script>
{% endraw %}

There's a few things going on here :

  1. {% raw %} tags wrap the whole set, just so our Hogan markup isn't touched by Twig
  2. <script type="text/template"> tags wrap the template block. This makes sure the client browser interprets this correctly on render
  3. {{#hits}} .. {{/hits}} tags wrap our repeating results. This is the Hogan equivalent of a Twig {% for .. %} loop
  4. {{{ summary }}} has triple braces because we expect the summary to contain markup and want it output raw

B. No Results

As well as the results template, we need to handle a no-results template.

{% raw %}
<!-- No-Results template -->
<script type="text/template" id="no-results-template">
    <div id="no-results-message">
        <p>We didn't find any results for the search <em>"{{ query }}"</em>.</p>
    </div>
</script>
{% endraw %}

That's much the same as the results template, just using the {{ query }} variable to output the search term.

C. Pagination

We'd also likely want a pagination template.

{% raw %}
<!-- Pagination template -->
<script type="text/template" id="pagination-template">
    <ul>
        <li {{^prevpage}}class="disabled" {{/prevpage}}>
        <a href="#" {{#prevpage}}class="go-to-page" data-page="{{ prevpage }}" {{/prevpage}}><
        </a></li>
        {{#pages}}
        <li class="{{#current}}active{{/current}} {{#disabled}}disabled{{/disabled}}">
            <a href="#" {{^disabled}} class="go-to-page" data-page="{{ number }}" {{/disabled}}>{{ number }}
            </a></li>
        {{/pages}}
        <li {{^nextpage}}class="disabled" {{/nextpage}}>
        <a href="#" {{#nextpage}}class="go-to-page" data-page="{{ nextpage }}" {{/nextpage}}>></a>
        </li>
    </ul>
</script>
{% endraw %}

You'll see much of the same going on here as before, is similar in behaviour to a native Craft pagination template block.

Is Hogan Required? Not at all. You can use any results markup setup you'd prefer. We prefer Hogan because it's so close to the native Twig, and makes for easily understandable markup with Craft.


3. Add our Javascript

With our markup in place we now need to actually hook it all up together. This involves adding a few javascript libraries onto the page.

A. Add the required javascript

Based on our setup we'll be using the following js libs :

  1. algoliasearch.js - this is the core algolia library that's doing all the search work against the api
  2. algoliasearch.helper.js - a set of helpers we use for state retention, population and to handle search-as-you-type request queuing
  3. hogan.js - the javascript templating library to parse the results
  4. searchplus.js - a ready to go helper specific to our implementation. This is optional if you want to roll your own configuration

All the libraries are included in the SearchPlus resources, so can be added directly via Craft's includeJsFile function like so :

{% includeJsFile resourceUrl('searchplus/js/searchplus-combined.min.js') %}

We're including the combined and minified library here, but you can add things individually if you prefer.

B. Hook it all up

Once you've added all the javascript, all that's left to do is trigger it on the page.

(function() {
    $(this).searchplus();
})();

That's it!

You should have a fully working, ready to go instant search page. See this exact setup on the Basic Search Demo

Basic Search Demo →

Grab the whole raw template