Nav bars, footers and menus

As we discussed in the 'Query with The $prismic Object' article ,to query content that is outside the SliceZone of your document (i.e. the body), you will need to perform another query. For menus or footers, it's a little different as you'll not want to query the menu on every page, we'll show you the best practice for doing this below.

Model your menu in Prismic.

In this simple example, we have created a Single type for the main menu as we won't be creating many versions of the document. We have a Title field and a Group field.

In the Group field's repeatable zone we added a Link field and a Rich Text field, this way you can add as many links as you need. From here you can create a new menu document in your dashboard and add your content.

{
  "Main" : {
    "title" : {
      "type" : "StructuredText",
      "config" : {
        "placeholder" : "Menu title...",
        "single" : "heading1"
      }
    },
    "menu_links" : {
      "type" : "Group",
      "config" : {
        "fields" : {
          "label" : {
            "type" : "StructuredText",
            "config" : {
              "single" : "paragraph",
              "label" : "Link Label",
              "placeholder" : "Link Label..."
            }
          },
          "link" : {
            "type" : "Link",
            "config" : {
              "label" : "Link",
              "placeholder" : "Select a Link..."
            }
          }
        },
        "label" : "Menu Links"
      }
    }
  }
}

Create your menu query.

The best way to do this is to perform the getSingle query for your menu in the Vuex Store. This is run once when your project is initialised.

export const state = () => ({
  menu: {}
})

export const mutations = {
  SET_MENU(state, menu) {
    state.menu = menu
  },
  SET_ERROR(state, error) {
    state.menu = error
  }
}

export const actions = {
  async fetchMenu({ commit }, $prismic) {
    try {
      const menu = (await $prismic.api.getSingle('menu')).data

      commit('SET_MENU', menu)
    } catch (e) {
      const error = 'Please create a menu document'

      commit('SET_ERROR', error);
    }
  }
}

Call the query in the layout.

In the Nuxt app layout you can call the query to your Single type menu and then pass this data to your menu component, in this case, the menu is in a component called 'HeaderPrismic'.

<template>
  <div class="homepage">
    <header-prismic/>
    <nuxt />
  </div>
</template>

<script>
import HeaderPrismic from '~/components/HeaderPrismic.vue'

export default {
  components: {
    HeaderPrismic
  },
  head () {
    return {
      title: 'Prismic Nuxt.js Multi Page Website',
    }
  },
  // Called before rendering the layout (even for error page)
  async middleware({ store, $prismic }) {
    await store.dispatch('fetchMenu', $prismic)
  }
}
</script>

Create the menu component.

Below is our simple menu component from our Nuxt multi-page sample. We can now access the data in the from the Vuex Store with $store and implement it on the page.

 <template>
  <header class="site-header">
    <p v-if="$store.state.menu === 'Please create a menu document'" class="logo">{{ $store.state.menu }}</p>
    <nuxt-link to="/" class="logo">{{ $prismic.asText($store.state.menu.title) }}</nuxt-link>
    <nav>
      <ul>
        <li v-for="menuLink in $store.state.menu.menu_links" :key="menuLink.id">
          <prismic-link :field="menuLink.link">{{ $prismic.asText(menuLink.label) }}</prismic-link>
        </li>
      </ul>
    </nav>
  </header>
</template>

<script>
export default {
  name: 'header-prismic',
}
</script>

That's it! Simple, fast statically deployed menus.

9 Rue de la Pierre Levée, 75011 Paris