Setup Algolia InstantSearch on Nuxt/Vue

August 19, 2020

I shall setup Algolia InstantSearch on client side only.

Install

npm install vue-instantsearch algoliasearch instantsearch.css

Setup

Create plugins/init-client.js

import Vue from 'vue'
import InstantSearch from 'vue-instantsearch'

Vue.use(InstantSearch)

Edit nuxt.config.js

export default {
  // ...
  plugins: [
    // ...
    { src: '~/plugins/init-client', mode: 'client' },
    // ...
  ],
  // ...
}

Usage

Create pages/search.vue. Replace

  • index-name (Under Indices in Algolia Dashboard)
  • Application ID (Under API Keys in Algolia Dashboard)
  • Search-Only API Key

A few changes are made

  • Prevent search/listing if there if no query
  • Show result in row instead of grid
  • Hide pagination if only 1 page of result
<template>
  <div>
    <client-only>
      <ais-instant-search
        :search-client="searchClient"
        index-name="live"
      >

        <ais-search-box />

        <ais-hits>
          <div slot="item" slot-scope="{ item }">
            <!-- show name -->
            <h2><ais-highlight attribute="name" :hit="item"/></h2>
            <!-- show content -->
            <div>{{ item.content }}</div>
            <!-- show content with highlight -->
            <div><ais-highlight attribute="content" :hit="item"/></div>
            <!-- show content with snippet: need to setup Snipetting in Indices -->
            <div><ais-snippet attribute="content" :hit="item"/></div>
          </div>
        </ais-hits>

        <ais-state-results>
          <template slot-scope="{ state: { query }, results: { hits, nbPages } }">
            <!-- show no result if query with no hits -->
            <div v-if="query && hits.length == 0">No results</div>
            <div v-else></div>

            <!-- hide pagination if 1 or less pages -->
            <ais-pagination v-if="nbPages > 1"/>
          </template>
        </ais-state-results>

      </ais-instant-search>
    </client-only>
  </div>
</template>

<script>
import algoliasearch from 'algoliasearch/lite'
import 'instantsearch.css/themes/algolia-min.css'
// import 'instantsearch.css/themes/reset-min.css'


const algoliaClient = algoliasearch(
  '3P********', // Application ID
  '0a5f4c5c0b18********************'  // Search-Only API Key
)

// this setup is required to prevent search on empty query
const searchClient = {
  search(requests) {
    if (requests.every(({ params }) => !params.query)) {
     return Promise.resolve({
        results: requests.map(() => ({
          hits: [],
          nbHits: 0,
          nbPages: 0,
          processingTimeMS: 0,
        })),
      });
    }

    return algoliaClient.search(requests);
  },
};


export default {
  data() {
    return {
      /*
      searchClient: algoliasearch(
        '3P********', // Application ID
        '0a5f4c5c0b18********************'  // Search-Only API Key
      ),
       */
      searchClient
    }
  },
};
</script>

<style>
/* add bottom margin to search box */
.ais-SearchBox {
  margin-bottom: 1em;
}

/* change search result from grid/box to row */
.ais-Hits-item {
  width: 100%;
  border: none;
  box-shadow: none;

}

/* prevent highlight overwrite font-size */
.ais-Highlight {
  font-size: inherit;
}
.ais-Highlight-highlighted {
  font-size: inherit;
}
</style>

More

This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.