Use Route Parameters

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.

🕙 Before you proceed...

This page assumes that you already have a project set up with Vue.js, Vue Router, and @prismicio/vue. If you haven't already set up Prismic, please visit the setup page.

You will also need to configure your HTML Serializer to handle Vue links, as explained in the section on Advanced Templating.

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.

What happens if you don't react to parameter changes?

If you do not explicitly react to parameter changes in your project, you will run into one main issue. When you click on a link to an internal route, the URL will change in your browser but your webpage will not actually update.

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.

Copy
  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:

Copy
{
  "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:

Copy
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:

Copy
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.

Copy
<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.