Search code examples
vuejs2vue-routerquasar-frameworkquasar

Passing an ID to Quasar and use of guards with children components on default setup


I'm trying to work with the default setup in Quasar and having a hard time with the most basic operation.

I have a list of tasks at the route /tasks which links to individual items at task/taskId (ie, task/5).

I had this setup using vue and vue-router previously and was setting the ID and loading the appropriate record with the beforeRouteUpdate guard and it was great. Then I switched to Quasar, setup with the basic cli. The task route is now a child of the main layout component which means beforeRouteUpdate is not called from within the child. I've tried using beforeEnter as a per-route guard, which, in the documentation says it has access to 'this', but it results to undefined.

I must be missing something because routing to /tasks and task/5 should be fundamental and I would think there's a best practice for achieving this within the default Quasar install.

My routes:

{
  path: '/tasks',
  name: 'tasks',
  component: () => import('layouts/MyLayout.vue'),
  children: [
    { path: '', component: () => import('pages/tasks/Index.vue') }
  ]
},
{
  path: '/task/:taskId',
  name: 'task',
  component: () => import('layouts/MyLayout.vue'),
  children: [
    { path: '', component: () => import('pages/tasks/Show.vue') }
  ],
  props: true
},

I'm not sure what other code to include, no sense in posting the beforeRouteUpdate from my child component since it's not called. I can't put in the parent component MyLayout.vue because that runs for all pages, not just tasks. Is there a best practice for refreshing the data using the prop from the router?


Solution

  • As far as I can see you are loading the same component for /tasks and for /task/:taskId.

    So this is not a Quasar problem but a Vue Router one. Vue Router in order to be optimal when sees the same component for the same route is not destroying and recreating the component.

    As solution, in the <router-view></router-view> component you can add a key so when you switch route the component will re-render:

    <router-view :key="$route.path"></router-view>
    

    Another solution would be to add a watcher to the MyLayout.vue component, so whenever the route changes, that watcher will be executed but the component will not be destroyed and re-created.

    watch: {
     // will fire on route changes
    '$route': {
      handler(newRoute) {
        if (newRoute.params.taskId) { // if it has `taskId` prop
          // you are in the `/task/:taskId` route
          // add your code here
        }
      },
      immediate: true,
      deep: true
    }