Use Case: Menus

Learn how to create menus in Nuxt.

You’ll need to query the menu on every page, so we’ll show you the best practice for doing this below. This example is a fragment of our Multi-page sample project.


Model your menu in Prismic.

In this example, we have created a Single type custom type for the menu as we will be creating one version of the document. We have a title field and a group field inside the menu type.

In the group field, we added a link field and a rich text field; this way, you can add as many links as you need. Then, create a new menu document in your dashboard and add your content.

In your customtypes folder, add a folder called menu, then copy and paste this JSON into a file called index.json (You’ll see it once you refresh Slice Machine):

{
  "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"
      }
    }
  }
}

Query the menu

The best way to do this is to perform the getSingle query for your menu in the Vuex Store. The query runs when your project initializes.

store/index.js
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. The menu is in a component called ‘HeaderPrismic’ (We’ll create it in the next step).

layouts/default.vue
<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 a header

We can now access the data from the Vuex Store with $store and implement it on the page.

components/HeaderPrismic.vue
<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>