Nach der Integration eines Tag-Systems in unseren NuxtJS/Prismic.io Blog, kommt nun eine weitere wichtige Funktion für die Auffindbarkeit von Inhalten in einem Blog, der Suche.
Glücklicherweise bietet die API von Prismic.io eine Volltext-Suche, so lässt sich diese Funktion doch recht einfach in den Blog integrieren.
Im Editor von Prismic müssen wir nichts verändern oder eintragen.
Suchleiste
Für die Suchleiste erstellen wir eine Komponente unter “/components/SearchForm.vue”. Diese Komponente kann dann in Seite, Header, Footer oder Sidebar integriert werden.
Für die Suchanfrage verwenden wir ein einfaches HTML-Formular. Der Übersicht halber habe ich die Klassen und das Icon erst mal entfernt. Den kompletten Code gibt es auf 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>
Nach der Eingabe des Suchbegriffes und der Betätigung des Submit-Buttons wird der Besucher auf example.com/search?search=”xxx” weitergeleitet. In der URL ist der Suchbegriff direkt angegeben.
Suchergebnisse
Für die Darstellung der Suchergebnisse erstellen wir nun “/pages/Search.vue”.
Die Query für Prismic ist recht simple aufgebaut. Als Suchwort wird der Parameter aus der URL verwendet. Um nicht auch die Tags als Ergebnis zu bekommen, ist die Suche auf den Artikeltyp “Post” limitiert. Sortiert wird absteigend nach dem Erstellungsdatum und das Ergebnis ist auf 9 Artikel limitiert.
// 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 } )
Der Array der Ergebnisse wird dann, wie schon auf der Startseite und Übersichtsseite der Tags, über die GridPost Komponente angezeigt.
Wie schon auf der Startseite, ist hier auch eine Pagination, also die Unterteilung in mehrere Abschnitte, eingebaut. Außerdem wird das Suchwort und ein neues Suchfeld angezeigt.
Im kompletten sieht diese Seite so aus:
<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>
Im nächsten Teil dieser Tutorial-Serie geht es um das Hinzufügen von ähnlichen Artikel unter einem Artikel.