Use Route Parameters

Vue Router doesn't re-render a component when a route parameter is changed. Here we discuss how to handle this issue in your Prismic project.

If you want to create a multi-page Vue.js app, you’ll need to use Vue Router. On this page, you’ll learn how to create a component that changes based on the URL.


Vue Router offers a link component that will change the URL in the user’s address bar. However, changing the URL alone doesn’t change the page. You need to write additional code to make the content of the page match the URL.

Reacting to parameter changes

Your Vue app will need to react to URL changes. For instance, if you have a “blog_post” component that renders at the path /blog/:uid, your app must update when a user navigates from /blog/hello-world to /blog/fizz-bang. When the URL changes, the component should send a new query to Prismic for the “fizz-bang” document and update the page with the new data.

How to react to parameter changes

To handle this issue, you just need to add a bit of code in the beforeRouteUpdate guard. Inside it, you have access to the destination route params. Use that route parameter to invoke the method that handles your query. This will update your template with the correct Prismic content based on the intended route.

The following is a basic example of how to fix this issue. In this case, the Vue component uses the Prismic document UID as a route parameter.

  data() {
    return {
      // Initialize "document"
      document: null
    }
  },
  methods: {
    async getContent(uid) {
      // Query the API and assign the response to "document"
      this.document = await this.$prismic.getByUID('post', uid)
    }
  },
  created() {
    // Call the API query method on page load
    this.getContent(this.$route.params.uid)
  },
  beforeRouteUpdate(to, from, next) {
    // Call the API query method when the URL changes
    this.getContent(to.params.uid)
    next()
  }

Example: Blog post

We will now go through a complete example using Vue Router route params. Let’s look at the case of blog posts. In Prismic, each blog post has a unique identifier, called a UID. We will assume that our blog posts have a URL /blog/[uid]. Within Prismic, our blog post custom type will have a UID field and a rich text field, like so:

{
  "Main": {
    "uid": {
      "type": "UID",
      "config": {
        "label": "UID"
      }
    },
    "rich_content": {
      "type": "StructuredText",
      "config": {
        "multi": "paragraph, preformatted, heading1, heading2, heading3, heading4, heading5, heading6, strong, em, hyperlink, image, embed, list-item, o-list-item, o-list-item",
        "allowTargetBlank": true,
        "label": "Rich content"
      }
    }
  }
}

In your Vue Router configuration, define a route for the blog posts based on the document UID:

import Vue from "vue";
import Router from "vue-router";
import BlogPost from "path/to/BlogPost.vue";

Vue.use(Router);

const router = new Router({
  routes: [
    {
      path: "/blog/:uid",
      name: "blog-post",
      component: BlogPost,
    },
  ],
});

export default router;

Also, define your blog URLs in your link resolver function to match the URL structure in your Vue Router config:

export default function (doc) {
  if (doc.isBroken) {
    return "/not-found";
  }

  if (doc.type === "blog_post") {
    return "/blog/" + doc.uid;
  }

  return "/not-found";
}

We’ll assume the content is rendered in a Vue component named BlogPost.vue.

We will update our component with the beforeRouteUpdate method. When a parameter change occurs, the component will call the getContent method with the document UID of the destination route.

<template>
  <div>
    <prismic-rich-text :field="fields.richContent"/>
  </div>
</template>

<script>
export default {
  name: 'BlogPost',
  data () {
    return {
      fields: {
        richContent: null
      }
    };
  },
  methods: {
    async getContent (uid) {
      const document = await this.$prismic.client.getByUID('blog_post', uid);
      this.fields.richContent = document.data.rich_content;
    }
  },
  created () {
    this.getContent(this.$route.params.uid);
  },
  beforeRouteUpdate (to, from, next) {
    this.getContent(to.params.uid);
    next();
  }
};
</script>

Now, when a user clicks a link to another blog post, the page will update with the new blog post.