Tag-System für ein Prismic.io / NuxtJS Blog

Das Grundgerüst für unseren Blog mit Prismic.io und NuxtJS steht. Nun können wir weitere praktische Funktionen hinzufügen.

Nicht nur für ein selbst, auch für die Leser ist eine Art von Sortierungssystem wichtig, um Artikel zu finden. Zwar bietet Prismic.io ein eingebautes Tagging-Systems. Dies ist aber sehr rudimentär, hat einige Einschränkung und sollte lieber nicht hierfür verwendet werden.

Was nun? Wir erstellen einfach unser eigenes System. Dazu erstellen wir einen neuen wiederholbaren Artikeltyp. Wie wir diesen in Prismic nennen ist eigentlich egal. Das kann sein “Tag” oder “Kategorie”. Natürlich kann man auch mehrere Sortierungssysteme erstellen. Das ist ganz abhängig davon, wie man seine Inhalte strukturieren möchte.

Artikeltyp in Prismic.io erstellen

Dem neuen Artikeltyp “Tag” können nun auch wieder verschiedene Felder zugeteilt werden. Hier zeigt sich nun auch wieder eine der Stärken dieses Systems, das nach belieben angepasst werden kann.

Für dieses Beispiel fügen wir ein Slug, Titel und Beschreibungsfeld hinzu. Weiter denkbar wäre auch ein Bildfeld oder Einstellungsmöglichkeiten für die Darstellung im Frontend.

Der zweite Schritt ist das Hinzufügen eines neuen Feldes in unserem “Post” Artikeltyp. Das “Content Relationship” Feld ermöglicht die Verbindung zwischen verschiedene Einträgen. Dies schränken wir auf den Artikeltyp “Tag” ein. Da wir mehr als einen Tag pro Artikel zuweisen möchten, muss das Feld in einem “Group” Feld sein. Befindet es sich in so einem, kann es mehrfach im Artikel wiederholt werden.

Um ein Tag einem Artikel zuweisen zu können, muss dieser erst erstellt werden. Anschließend kann er über das Feld im Artikeleditor ausgewählt werden. Schön wäre die Möglichkeit, diesen direkt beim Schreiben des Artikels einrichten zu können.

prismic-editor-tag
tag-blog-prismic-category

Frontend

Nun können wir unsere Tags auch im Frontend darstellen lassen.

Übersicht

Als Erstes erstellen wir mal eine Übersichtsseite für einen bestimmten Tag. Auf dieser sollen neben den Daten über unseren Tag, auch alle mit ihm verbundenen Artikel gelistet werden. Dazu erstellen unter “/pages/tag” die Datei “_uid.vue”. Wie schon bei den Artikel, sind die Tags unter dem jeweiligen Slug erreichbar. Beispiel: example.com/tag/fashion

<template>
  <main class="col-start-2 col-end-12">
    <div>
      <h1
        class="text-4xl tracking-wider text-center uppercase text-bold"
      >{{ $prismic.asText(title) }}</h1>
      <div class="w-1/12 mx-auto mt-2 border-b-4 border-gray-400"></div>
    </div>

    <div
      class="w-10/12 mx-auto mt-8 mb-16 text-sm italic description"
      v-if="description.length > 0">

      <prismic-rich-text :field="description" />

      <div class="w-1/2 mx-auto mt-4 border-b-2 border-gray-400"></div>
    </div>

    <div v-if="posts.length > 0" class="grid grid-cols-12 row-gap-16 md:col-gap-16">
      <div v-for="post in posts" :key="post.id" class="col-span-12 md:col-span-4">
        <GridPost :postdata="post" :imgsize="'(min-width: 768px) 33vw, 90vw'" />
      </div>
    </div>
  </main>
</template>

<script>
import GridPost from '~/components/GridPost'

export default {
  name: 'Tag',
  components: {
    GridPost
  },
  async asyncData({ $prismic, params, error }) {
    try {
      // Query tag
      const tag = await $prismic.api.getByUID('tag', params.uid)

      // Query all posts with this tag
      const posts = await $prismic.api.query(
        [
          $prismic.predicates.at('document.type', 'post'),
          $prismic.predicates.at('my.post.tags.tag', tag.id)
        ],
        { orderings: '[document.first_publication_date desc]' }
      )

      // Returns data to be used in template
      return {
        title: tag.data.title,
        description: tag.data.description,
        posts: posts.results
      }
    } catch (e) {
      // Returns error page
      error({ statusCode: 404, message: 'Page not found' })
    }
  }
}
</script>

Die erste Query fragt nach dem Eintrag des Tags. In der zweiten Query lassen wir uns alle Artikel mit dem Artikeltyp “post” geben, die zusätzlich einen Eintrag im Content Relationship Feld mit der ID unseres Tags haben.

Der Titel und die Beschreibung des Tags wird anschließend ganz normal angezeigt. Der Array an Artikel wird durch die Komponente “GridPost”, welche wir schon zuvor auf der Startseite verwendet haben, dargestellt.

overview-tag-blog-prismic

Artikel-Ansicht

Mit einem Klick auf einen der Einträge auf der Übersichtsseite, kommen wir zu unserer Artikel-Ansicht des Prismic Blogs, auch dort sollen die verwendeten Tags angezeigt werden.

Zwar befindet sich im Ergebnis der eigentlichen Anfrage des Artikels auch das Content Relationship Feld, aber dort befinden sich nicht die Felder des Tag selbst. Möchten wir also den Namen oder andere Informationen anzeigen, müssen wir eine weitere Query senden. Hier wäre es praktisch, wenn Prismic.io eine Möglichkeit bieten würde bestimmte Felder in die jeweiligen Abfragen integrieren zu können.

Nachdem wir die Daten für den Artikel haben, erstellen wir ein Array mit allen IDs der Tags. Diese IDs verwenden wir für eine zweite Query, bei der wir alle Tags mit den entsprechenden IDs als Ergebnis bekommen.

<script>
export default {
  async asyncData({ $prismic, params, error }) {
    try {
      // Query post
      const post = await $prismic.api.getByUID('post', params.uid)


      // Query tags
      let tagids = []
      post.data.tags.forEach(tag => {
        tagids.push(tag.tag.id)
      })

      const tags = await $prismic.api.getByIDs(tagids)

      // Returns data to be used in template
      return {
       …
        tagdata: tags.results
      }
    } catch (e) {
      // Returns error page
      error({ statusCode: 404, message: 'Page not found' })
    }
  }
}
</script>

Das Ergebnis kann dann etwa so im Template-Part dargestellt werden.

<li class="tags" v-for="tag in tagdata" :key="tag.id">
{{ $prismic.asText(tag.data.title) }}
</li>

Natürlich kann man die Tags noch an weiteren Stellen in seinem Prismic.io/NuxtJS Blog einbauen.

Im nächsten Teil geht es um die Integration einer Suchfunktion in unseren Blog.