After the integration of a tag system into our NuxtJS/Prismic.io blog, now comes another important function for finding content in a blog, the search.
Fortunately, Prismic.io’s API offers a full text search, so this feature can be integrated into the blog quite easily.
In the Prismic editor, we don’t have to change or add anything.
Search bar
For the search bar we create a component under “/components/SearchForm.vue”. This component can then be integrated into page, header, footer or sidebar.
For the search query we use a simple HTML form. For the sake of clarity I have removed the classes and the icon for now. The complete code is available on Github.
<form action="/search"> <input type="search" name="search" id="search" placeholder="Search" v-model="searchinput" class="w-full outline-none appearance-none focus:outline-none active:outline-none" /> <button type="submit" class="ml-1 text-gray-400 outline-none hover:text-black focus:outline-none active:outline-none" ></button> </form>
After entering the search term and pressing the submit button, the visitor is redirected to example.com/search?search=”xxx”. The URL contains the search term directly.
Search results
For the presentation of the search results we now create “/pages/Search.vue”.
The query for Prismic is quite simple. The parameter from the URL is used as the search word. In order not to also get the tags as a result, the search is limited to the article type “Post”. Sorting is done in descending order by creation date and the result is limited to 9 items.
// Query for keyword const searchresult = await $prismic.api.query( [ $prismic.predicates.at('document.type', 'post'), $prismic.predicates.fulltext('document', query.search) ], { orderings: '[document.first_publication_date desc]', pageSize: 9 } )
The array of results will then be displayed via the GridPost component, as on the start page and overview page of the tags.
As already on the start page, a pagination, i.e. the division into several sections, is also built in here. In addition, the search word and a new search field are displayed.
The complete page looks like this:
<template> <main class="col-start-2 col-end-12"> <div class="mb-16 text-2xl Search"> <div> <strong>Results for:</strong> {{searchterm}} </div> <div class="w-1/12 mt-2 border-b-4 border-gray-400"></div> </div> <div v-if="result.length > 0" class="grid grid-cols-12 row-gap-16 md:col-gap-16"> <div v-for="post in result" :key="post.id" class="col-span-12 md:col-span-4"> <GridPost :postdata="post" :imgsize="'(min-width: 768px) 33vw, 90vw'" /> </div> <div class="flex col-span-12 mt-16 loadmore"> <button class="px-8 py-2 mx-auto text-lg text-center border-2 border-black border-solid cursor-pointer dark-mode:border-white hover:border-accent-dark" @click="loadMoreResults()" v-if="result.length % 9 === 0 && !nonewposts" >Load more results</button> <button v-else class="px-8 py-2 mx-auto text-lg text-center border-2 border-black border-solid cursor-pointer dark-mode:border-white" >You reached the bottom!</button> </div> </div> <div v-else class="text-xl font-semibold">Sorry, no result</div> <div class="w-2/3 mx-auto my-16 md:w-1/2 searchform"> <div class="mb-4"> <div class="text-2xl">Change your search</div> <div class="w-1/12 mt-2 border-b-4 border-gray-400"></div> </div> <SearchForm :currentinput="searchterm" /> </div> </main> </template> <script> import GridPost from '~/components/GridPost' import SearchForm from '~/components/SearchForm' export default { name: 'Search', components: { GridPost, SearchForm }, data() { return { currentpage: 1, nonewposts: false } }, async asyncData({ $prismic, error, query }) { try { // Query for keyword const searchresult = await $prismic.api.query( [ $prismic.predicates.at('document.type', 'post'), $prismic.predicates.fulltext('document', query.search) ], { orderings: '[document.first_publication_date desc]', pageSize: 9 } ) // Returns data to be used in template return { result: searchresult.results, searchterm: query.search } } catch (e) { // Returns error page error({ statusCode: 404, message: 'Page not found' }) } }, methods: { async loadMoreResults() { try { // Query other page for search const searchresult = await this.$prismic.api.query( [ this.$prismic.predicates.at('document.type', 'post'), this.$prismic.predicates.fulltext('document', this.searchterm) ], { orderings: '[document.first_publication_date desc]', pageSize: 9, page: this.currentpage + 1 } ) if (searchresult.results.length > 0) { // Merge with the other posts this.result = this.result.concat(searchresult.results) } else { // No more new posts this.nonewposts = true } // Save current page this.currentpage++ } catch (e) { console.error(e) } } } } </script>
The next part of this tutorial series is about adding similar articles under an article.