Pass dynamic data to router-link. - javascript

I'm trying to pass a dynamic path to vue-router but I can't seem to give it the correct syntax. Here is what I'm trying.
<li v-on:click="$emit('closeDropdown')"><router-link to="item.route" id="button">{{ item.title }}</router-link></li>
Is just wrapping it in quotes not enough because this is what I see when I inspect the elements: href="#/item.route" for all items.
PARENT COMPONENT
<UserDropdownList v-for="item in userDropdownItems" v-bind:item="item"></UserDropdownList>
data: function () {
return {
userDropdownItems: [
{ title: 'Profile', route: "/profile" },
{ title: 'Users', route: "/users" }
]
}
}
How can I access the route property for the Router-link to attribute?

Using Dynamic Route Parameters
If you take a look at the vue-router documentation, what you're describing sounds very much like a job for dynamic route parameters:
const router = new VueRouter({
routes: [
// dynamic segments start with a colon
{ path: '/user/:id', component: User, name: 'user' }
]
});
Then, to generate a link via <router-link> for said route, you'd do the following:
<!-- named route -->
<router-link :to="{ name: 'user', params: { id: 123 }}">User</router-link>
Directly using variable with router-link
To use variables in a router link, all you have to do is this:
<router-link :to="item.route" id="button">{{ item.title }}</router-link>
Adding a colon (:) before the to attribute tells Vue that you're about to use some javascript in there.
Using query parameters
Instead of using dynamic route parameters OR js variables, you could use the query option instead:
<!-- with query, resulting in `/register?plan=private` -->
<router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>
Hope this helps! I've attached all the documentation sources where I found this. I highly recommend giving it a solid look through, as it is one of the most well-written documentation sites I've ever come across.

Related

Pass Vue query parameter from current route to router-link

I know this cannot be this difficult, all I want to do is detect the query parameter and pass it to my component. What do I have to do to access router from a component in Vue?
<router-link :to="{ path: '/', query: { myQuery: /*query parameter here/* } }" >Go There</router-link>
No matter what I do I can't figure it out. I've tried everything I can find online, and for some reason in Vue "this" doesn't exist, and I'm literally ready to give up and go back to Angular.
Seriously, I can't even access it inside the tag, and importing the actual router from the routing file does nothing.
How do I make this happen? I feel like it shouldn't be this complicated just to get query parameters from the url in ANY framework. I've been reading manuals all day, can somebody please just help me out here?
The current route's query is in this.$route.query and you can pass that entire query object on to another route if you want to preserve it in the destination:
<router-link
:to="{ path: '/', query: $route.query }"
>
Go There
</router-link>
If you only want to pass a specific query param:
<router-link
:to="{ path: '/', query: { myQuery: $route.query.myQuery }}"
>
Go There
</router-link>

Navigating to a new optional base route while maintaining the current nested routes - Vue Router

Please may someone help me with a params/named route question.
I'm trying to achieve an optional named route change at the first level while maintaining nested structure. Is there a way to achieve this using named routes?
For example imagine use case, either:
/europe/train
or
/car/europe/spain
I would have a new named route going to train instead of car and the behaviour to link to the full path of:
/train/europe/spain
Currently this takes you to the base route with the first level /train removing nested routes, you then need to reselect Europe and Spain.
This is the current setup I'm trying to achieve this:
path: '/:transportSlug?',
name: 'Transport',
...
children: [
{
path: ':regionSlug',
name: 'Region',
...
children: [
{
path: ':countrySlug',
name: 'Country',
...
<router-link :to="{
name: 'Transport',
params: {
transportSlug: filter.slug,
regionSlug: region.slug,
countrySlug: country.slug
}
}">
This is passing in 3 params when navigating to a new base route and all 3 are being correctly passed. I can output them in the view which makes me think it may be a technical limitation/misunderstanding somewhere.
I'm aware of path routing and creating the full path with a computed properly.
Example here
Thank you.
With help from Posva from Vue I was able to solve this.
My approach and understanding of how Vue Router worked was slightly incorrect by thinking that you needed to reference the named route in a nested tree that you wanted to update.
To update the Transport type in /euope/spain I would need to instead reference the Country named route and update the param for the transport.
<router-link :to="{
name: 'Country',
params: {
transportSlug: filter.slug,
}
}">
This maintains the correct URL while updating the Transport type.
Hope this may be of some help to someone.

VueJS pushing route with params shows old params in browser

Scenario
I've a app where I use vue.js 2.6 and vue-router 3.0
in there I've links to detail pages like this
<div v-for="item in items">
<router-link :to="{name: 'details', params: {key: item.shortKey}}">
</div>
what works
Now in the target view the parameter always has the correct value
Also when I first time click a link then I see the correct shortkey in the browser.
Not working
Now when I click another itemm I still see in the browser url the key of the item that was clicked first in the browser . Eventhough inside the code the route.params do have the correct value.
Both the View browser tools and the code itself have the correct value.
What am I missing?
Also using router.push has the same result. Changing from history to hash mode also doesn't change the behavior
Shortened Router config
const routes = new Router({
mode: 'history',
routes: [{
component: layout,
path: '/',
children: [
{
path: '/',
name: 'home',
component: Home,
meta:{display:"home"}
},
{
path:'list',
name:'list',
component: listItemsComponent,
},
{
path: 'details/:key',
name: 'details',
component: detailComponent
},
]
}]
});
Try adding a unique key to each element in v-for like below -
<div v-for="item in items" :key="item.id">
<router-link :to="{name: 'details', params: {key: item.shortKey}}">
</div>
As per vue js docs,
To give Vue a hint so that it can track each node’s identity, and thus
reuse and reorder existing elements, you need to provide a unique key
attribute for each item.
You can try to add '/' in your path : path: '/details/:key'

Vue.js passing array from one page to another

I'm using vue.js and I have one component, where the user selects what they want and then they hit "order". At this moment I use <router-link to="/order"> to show new page. But I don't know how to access the array from the previous component there. I tried something like this :selected-chairs="selectedChairs" and in the other component this props: ['selectedChairs'], but it doesn't work.
My routes file (index.js):
export default new Router({
routes: [
{
path: '/',
name: 'Select',
component: Select,
props: true
},
{
path: '/order',
name: 'Order',
component: Order,
props: true
}
]
})
It's possible to do what you want to do but I don't think it's a good idea. First, in line with your original question, this is what you could do:
Set up your order route:
export default new Router({
routes: [{
path: '/order/:selected-chairs',
name: 'Order',
component: Order,
props: true
}]
}
You could then have a link like so:
<router-link :to="'/order/' + JSON.stringify(mySelectedChairs) + '">Link Text</router-link>
or you could do
<router-link :to="{path: 'order', query: { selected-chairs: mySelectedChairs }}">Link Text</router-link>
This would allow you to access that data on your component using:
this.$route.params.selected-chairs
or
this.selectedChairs // because props: true binds to the props
This page has more information on passing params using router-link: https://router.vuejs.org/en/api/router-link.html
As I said, I don't think this is a good idea. Even if you're not using Vuex, you're much better off doing this using some sort of stateful component. You could then set the selected-chairs in your state and the order component would just know about them being selected. This allows you to do things like having a mini basket that reacts to users entering stuff into their baskets etc.
Setting up a simple Vuex system isn't complicated and there are various articles on the web to help that would be my recommended approach.
The above answer is correct but will show a blank page on page load.
To solve that, DO:
export default new Router({
routes: [{
path: '/order/:selected-chairs?',
name: 'Order',
component: Order,
props: true
}]
}
As you can see, I added a question mark (?) to the front of the path parameter

Rendering a child route in the parent in Angular 4

With Angular 2, I could make a child route render "over" its parent by defining an empty path and creating an essentially empty base component. I am trying to accomplish something similar with the new Angular router (version 4.3.1), but have hit a roadblock.
To reproduce my problem, here's a Plunker. The routes are defined as:
[{
path: '',
redirectTo: "/master",
pathMatch: "full"
}, {
path: 'master',
component: MasterComponent,
children: [{
path: 'detail/:value',
component: DetailComponent,
children: [{
path: 'subdetail',
component: SubDetailComponent
}]
}]
}]
When I navigate to a detail page, the master page is still visible because I have added a <router-outlet></router-outlet> to MasterComponent. What I need is to replace the master view with the detail. I can accomplish this by making detail/:value a sibling of master rather than a child, but this isn't logically correct in my application and breaks my breadcrumbs.
Is there any proper way to handle this kind of pattern, or will I have to pick a workaround, such as showing and hiding the intended route or manually specifying a dedicated "main" outlet for every link?
The only existing solution that comes close is to define a dummy parent component, but this only works one-level down. If my detail page has another sub-detail page that should also replace master, it gets very messy.
Is there any route-level flag I can set or design pattern to implement to elegantly accomplish this? I am an Angular 2 beginner, but I feel as though something like this should be simple.
First, there is no "new" router in 4.3.1. It's the same router from 2.x.
Second, there were a few changes I needed to make to your plunker to make it work appropriately. The key change was this in the master.component.ts:
<a [routerLink]="['/detail', 5]">
I added a slash. Without the slash it was looking for a route named master/detail/5
The route definition is now flat, so everything will appear "under" your main header.
export const routes: Routes = [
{
path: '',
redirectTo: 'master',
pathMatch: 'full'
},
{
path: 'master',
component: MasterComponent
},
{
path: 'detail/:value',
component: DetailComponent
}
];
The updated plunker is here: https://plnkr.co/edit/EHehUR6qSi248vQPDntt?p=preview

Categories