Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue router: How to dynamically generate page titles for dynamic routes?

I have a simple Vue-based website created using Vue CLI, and I'm trying to figure out how to dynamically generate page titles for views w/ dynamic routes. The site is pulling JSON data from a headless CMS, and I have dynamic routes set up for detail views of a "project" content type. I have the dynamic route set up as follows:

// single project vue (dynamic)
{
    path: "/projects/:project_name_slug",
    name: "single-project",
    component: () =>
        import(
            /* webpackChunkName: "single-project" */ "./views/SingleProject.vue"
        ),
    meta: {
        title: "project detail",
    }
}

I have added the following, which works for adding static page titles:

// show page titles
const DEFAULT_TITLE = "my blog";
router.afterEach((to, from) => {
    // document.title = to.meta.title || DEFAULT_TITLE;
    document.title = "my blog - " + to.meta.title || DEFAULT_TITLE;
});

As it stands, upon visiting a project detail view, the title will read "my blog - project detail"; however, I'd like it to pull the actual project name from the JSON/field data for project_name (just as the route path is using project_name_slug), but nothing I've tried thus far has worked. For instance, using meta: { title: (route) => route.params.project_name } just results in a raw function text showing after "my blog - ". Thus, in cases for those dynamic views, I would like to.meta.title to resolve to the project name, creating "my blog - {project name}". Thank you for any assistance here, and please let me know if I need to provide any more details.

*Note: This question differs from that posed in this SO thread as my case involves dynamic routes using JSON data requested via Axios

like image 521
nickpish Avatar asked Dec 30 '22 16:12

nickpish


1 Answers

Set the meta in the router's beforeEach navigation guard:

router.beforeEach((to, from, next) => {
  to.meta.title = to.params.project_name_slug;
  next();
});

-or-

You could use the beforeRouteEnter and beforeRouteUpdate in-component guards:

export default {
  ...
  beforeRouteEnter(to, from, next) {
    to.meta.title = to.params.project_name_slug;
    next();
  },
  beforeRouteUpdate(to, from, next) {
    to.meta.title = to.params.project_name_slug;
    next();
  }
}

You can use the afterEach just like you would for a static meta since it will already be set:

const DEFAULT_TITLE = "my blog";
router.afterEach((to, from) => {
    // document.title = to.meta.title || DEFAULT_TITLE;
    document.title = "my blog - " + to.meta.title || DEFAULT_TITLE;
});

(Note: Using beforeEnter in the route definition wouldn't be enough because it doesn't trigger when going from one dynamic param to another. Even <router-view :key="$route.fullPath"></router-view> does not trigger beforeEnter when changing params.)

like image 116
Dan Avatar answered Jan 02 '23 06:01

Dan