0
votes

I have a VueJS application where I want to reuse the current tab when routing to grand-child routes. The child component is what is defined as the initial path for the tab and I want to remain on that tab when I route to the GrandChild route. Currently, when I use Router-link to redirect, it paints the tab as the active tab but displays the child component instead of the grandchild. My router view <router-view></router-view> includes the tabs as well as a header object. How could I setup a router-link to redirect to the grandchild component?

routes.js

{
  name: "parent",
  path: "/parent/:parentId(\\d+)",
  props: function(route) {
  let parentId = null;
  if (route.constructor === Array) {
        parentId = route[0].params.parentId;
  } else {
        parentId = route.params.parentId;
  }

  return {
        parentId: Number(parentId)
  };
},
  component: Parent,
  children: [
  {
    name: "child",
    path: "child",
    component: Child, 
    children: [
        {
        name: "grandchild",
        path: "grandchild/:grandchildId(\\d+)",
        props: function(route) {
        return { grandchildId: Number(route.params.grandchildId) };
        },
        component: GrandChild
        }
    ]
}

The tabs are dynamically created based on an Array passed into the Tabs component.

Tabs.vue

    <v-tabs background-color="primary" dark>
        <v-tab v-for="tab in tabs"
            :key="tab.id"
            replace
            :to="{
              path: tab.path
            }"
            >{{tab.name}}</v-tab
        >
    </v-tabs>
</template>

<script>
export default {
  props: {
    tabs: {
      type: Array,
      required: true
    }
  }
}
</script>

Here is a simplified version of the parent component. Its really just displays some basic information and then paints the tabs.

Parent.vue

<template>
  <v-container>
    
    <v-row>
      <v-col sm4>
        <v-card>
            <v-row no-gutters>
              <v-col>
                  HEADER HERE
              </v-col>
            </v-row>
        </v-card>
        <atomic-tabs :tabs="tabs"/> 
        <router-view></router-view>   
      </v-col>
    </v-row>
  </v-container>
</template>
<script>

import axios from "axios";
import Tabs from "@/components/Tabs";

export default {
  components: {
    "tabs": Tabs
  },
  props: {
    parentId: {
      type: Number
    }
  },
  data() {
    return {
      pageName: "Parent",
      tabs: [
        { id: 1, name: "child", path: `/parent/${this.parentId}/child`}
      ]
    };
  }
</script>
1
Can you also post the Parent component ? - Thomas Kuhlmann

1 Answers

0
votes

I think you have a pretty straight forward issue - you are nesting twice.

Option 1

You'd need another <router-view/> inside the child component to be able to see the grandchild with the current route configuration (and then hide the child content with v-show or something like that)

Option 2

Alternatively you could change the way you structure the child and grandchild routes, don't nest them:

{
  name: "parent",
  path: "/parent/:parentId(\\d+)",
  props: function(route) {
  let parentId = null;
  if (route.constructor === Array) {
        parentId = route[0].params.parentId;
  } else {
        parentId = route.params.parentId;
  }

  return {
        parentId: Number(parentId)
  };
},
  component: Parent,
  children: [
   {
    name: "child",
    path: "child",
    component: Child, 
   },
   {
    name: "grandchild",
    path: "child/grandchild/:grandchildId(\\d+)",
    props: function(route) {
    return { grandchildId: Number(route.params.grandchildId) };
     },
    component: GrandChild
   }
 
}

either way, the router link would be:

:to="{name:'grandchild', params:{grandchildId:'134551}}"

or

:to="'child/grandchild/${'123431')'"