Router link is throwing error when navigating away from route which contains a param vue js 3

Viewed 367

I am using Vue JS 3 and Vue Router. I have a company area of the app that uses a dynamic companyId parameter in the route. Ex. myapp.com/46/tasks where 46 is the companyId. Everything works fine when I navigate around to the different sub areas of the company area. However, if I am displaying a router link on any page, and that router link depends on the companyId parameter, if I try to navigate anywhere outside of the company area, which does not require the companyId, the reactivity of the router-link throws an error and the navigation does not happen. If I'm located at the route referenced above, and I try to navigate to

<router-link v-if="session.availableAccounts.length > 1" :to="{name: 'selectCompany'}">
    {{ session.selectedAccount.name }}
</router-link>

Here is the router-link that throws the error: (however this happens on any page, with any router-link that requires parameters from the existing page and I then try to navigate somewhere without passing in the parameters EVEN THOUGH THE PARAMETER IS NOT NEEDED FOR THE ROUTE I AM TRYING TO GO TO)

<router-link 
        :to="{ 
            name:'users', 
            query: { 
                selected: person.id, 
                area: 'Info' 
             }
           }">
           {{ person.name }}
</router-link>

Here is the portion of my router.js file concerning the 2 routes I am trying to move between.

       {
            path: '/account',
            component: Base,
            meta: {
                authorization: true
            },
            children: [
                {
                    name: 'newAccount',
                    path: 'new',
                    component: NewAccount,
                    meta: {
                        authorization: true,
                        title: 'New Account'
                    }
                },
                {
                    name: 'selectCompany',
                    path: 'selectAccount',
                    component: SelectCompany,
                    meta: {
                        authorization: true,
                        title: 'Select Account'
                    }
                },
                {
                    name: 'createCustomer',
                    path: 'create',
                    component: NewCustomerAccount,
                    meta: {
                        authorization: true,
                        title: 'Create Account'
                    }
                }   
            ]
        },        
        {            
            path: '/:companyId',
            component: Base,            
            meta: {
                authorization: true,
                nav: 'account'
            },
            children: [
                {
                    name: 'home',
                    path: 'tasks',
                    alias: '',
                    component: TaskManager,
                    meta: {
                        title: 'My Tasks'
                    },
                },
                ...
            ]
         }

This happens no matter what method I use to cause navigating, whether I use a router-link or whether I call router.push() in code. However the error always comes from a router-link. If I hide all router-links on the page the navigation works flawlessly. I tried to recreate this on a smaller scale app and I can't seem to make it happen, which means I am doing something wrong but I can't figure it out. I also can't find any similar issues here, which is typically a good indicator that I'm doing something wrong. There is definitely a work-around, where I can store that companyId in a Vuex store and pass it around in the route, but why should I have to pass in a parameter that is not actually in the route?! I really don't want to go down that route (pun intended) unless I absolutely have to. And I first ran into this problem with a child route of the company which needs a projectId parameter. I had the same issue when navigating away from /[:companyId]/[:projectId]/anywhere to /[:companyId]/anywhere IF and only if there is a router-link displayed on the page that relies on [:projectId], and in that situation I was actually relying on whether or not projectId existed within the route params to control a navigation menu. I developed a work around for that behavior but otherwise passing the projectId into the router push to keep the error from happening would have stopped my nav menu from updating correctly.

Is the problem that I do not explicitly define the dynamic route in the parameter? It seems like explicitly defining it would solve my problem but it also requires me to store that somewhere, effectively duplicating the data. I would rather have the id defined in one place (the route) rather than storing it in the store and the route and having to worry about keeping them in sync with each other. Is there no other way?

Any help is appreciated. Thanks.

1 Answers

As is normally the case when I ask a question I discover the answer while asking it. Just posting in case anyone else runs into this same issue. The solution is just to make sure that you explicitly provide the dynamic param when you declare the router-link. Not sure if I like that it lets you create the link without a warning that the required param has not been declared (while there is a warning if vue-router can't resolve the route).

My revised router-link:

            <router-link 
                :to="{ 
                    name:'users', 
                    params: { 
                        companyId: route.params.companyId 
                    }, 
                    query: { 
                        selected: person.id, 
                        area: 'Info' 
                    }
                }">
                {{ person.name }}
            </router-link>
Related