Is there a way to set a route prop in vue? - vue.js

I want to navigate to a specific tab in a page, with
this.$router.push({
name: "AdminNotifications",
params: { tab: "requests" },
})
so inside the page i can get the param and set the tab:
mounted() {
const routeTab = this.$route.params.tab;
if (routeTab) this.tab = routeTab;
}
It works if the current page is not AdminNotifications.
But else, there is an error:
NavigationDuplicated: Avoided redundant navigation to current
So... is there a way to just set the tab props, without navigate?
thanks

You can't navigate to a route if you're already there. But, since you're already there, you can just set this.tab to the desired value:
if (this.$route.name === 'AdminNotifications') {
this.tab = 'requests';
} else {
this.$router.push({
name: "AdminNotifications",
params: { tab: "requests" },
})
}
If the component in charge of navigating is not the same as the one containing tab, you could push the tab param to the $route:
if (this.$route.name === 'AdminNotifications') {
this.$router.replace({
params: { tab: "requests" }
});
} else {
this.$router.push({
name: "AdminNotifications",
params: { tab: "requests" },
})
}
And in the page component, replace the "watcher" in mounted with a proper watch, which sets tab to any truthy value of $route.params.tab, dynamically:
watch: {
'$route.params.tab': {
handler(val) {
if (val) {
this.tab = val;
}
},
immediate: true
}
}

If i understood your question correctly you can just do this.$route.params.tab = "any value" like any other variable. this.$route.params.tab is just a variable like all the others.

Here is how I was handling this with the vue-router.
Add one parent component which will contain tabs and a tab content components.
Your structure can looke like this:
tabs/Tab1.vue
tabs/Tab2.vue
tabs/Tab2.vue
Tab.vue
In Tabs.vue paste code below. The component should contain in the place where you want to display the content of your tabs and router-links to link a specific tab.
Tab.vue
<template>
<div class="tabs">
<router-link to="/tab1">Tab 1</router-link>
<router-link to="/tab2">Tab 2</router-link>
<router-link to="/tab3">Tab 3</router-link>
<router-view />
</div>
</template>
<script>
export default {
name: "tabs",
components: {},
};
</script>
Then fill tabs content components.
In your router.js register your tab routes as shown below.
import Tabs from "./Tabs";
import Tab1 from "./tabs/Tab1";
import Tab2 from "./tabs/Tab2";
import Tab3 from "./tabs/Tab3";
{
path: "/",
redirect: "/tab1",
component: Tabs,
children: [
{
path: "/tab1",
name: "tab1",
component: Tab1
},
{
path: "/tab2",
name: "tab2",
component: Tab2
},
{
path: "/tab3",
name: "tab3",
component: Tab3
}
]
}
Now you should be able to navigate a specific tab by router link.

In the file where you define the routes, you need to define the props for each route, something like this:
const routes = [
{
path: "admin-notifications",
name: "AdminNotifications",
component: AdminNotificationsView,
props: r => ({
tab: r.params.tab
})
}
]
And then define the prop tab in AdminNotificationsView assuming that's the component you use to render the view.

Related

Pass data through router to other component in vue

I am trying to pass data through router. My code is working but it shows data in url. I don't want that like as POST method.url should like /data-list . Also I want to catch passing value from component. Here I did not use vuex . Actually my job is to show message that task is done based on this data. I am using Laravel for backend. Thanks in advance
1st component
axios.post("/request/data", dataform).then(function (resp) {
app.$router.push({ path: "/data-list/" + resp.data.success });
});
routes
{
path: '/data-list/:message?',
name: 'dataList',
component: dataList,
meta: {
auth: true
}
},
Another component. Here I want to catch
mounted() {
var app = this;
app.message = app.$route.params.message;
}
So if I understand correctly, you are fetching data in some component and then you are doing a router-push to dataList component.
You want to access the data in dataList component.
Since you always want the route to be /dataList, do this in your routes file
{
path: '/data-list', //removing dynamic tag.
name: 'dataList',
component: dataList,
meta: {
auth: true
}
},
Then in the component where you do router push, add a handleClick like so.
handleClick() {
let data = {
id: 25,
description: "pass data through params"
};
this.$router.push({
name: "dataList", //use name for router push
params: { data }
});
}
}
Then in your dataList component you can access the data passed in the mounted like so :
mounted() {
let data = this.$route.params.data;
console.log("data is", data);
}
Working implementation attached below.
You can push router data in router like this.
this.$router.push({
name: "dataList",
params: { data: resp.data },
});
and in the routes you can define your route as
{
path: "/dataList",
name: "dataList",
props: true,
meta: { title: "Data list" },
component: () => import("path to datalist component")
},
and in the DataList.vue you can use props to get the data
export default {
props:['data'],
mounted(){
alert(this.data);
}
}

this.$route.params is empty in app.vue when building site global navigation (outside of router-view)

I have vue setup and working fine, I can route to pages, and they are shown correctly in the router-view component. I can access this.$route.params.xyz in the components within the page, however, when trying to access in a component, such as the global navigation, the params collection is empty.
The current route URL is localhost:5011/forum/2/details where the 2 is an id value. I can access the 2 happily on the page for some local routing, but I wanted a settings page, to be available on the global menu.
{
title: 'Forum Settings ',
icon: 'mdi-cogs',
text: 'Forum Settings ' + this.$route.params.id,
route: {
name: 'ForumSettings',
params: {
id: this.$route.params.id
},
},
},
However, params is {} and id is undefined.
How can I make this work?
route.js:
{
path: '/forum/:id/settings',
name: 'ForumSettings',
component: ForumSettings,
meta: {
authorize: true,
},
},
on the page itself as a test:
<dr-btn
text="Settings"
:to="{ name: 'ForumSettings', params: {id: this.$route.params.id}}"
>
<v-icon>mdi-cog</v-icon>
</dr-btn>
This works fine.
in the app.vue:
mounted() {
console.info('Mounted Router', this.$route);
},
This is not the current URL, so it seems the router isn't setup at this point. How can it be achieved to get the forum id for the current route (if it is on another page, the settings link will be hidden, so if actually no id, then no menu item)
You could use a vuex store. Have the page that needs settings pass the id param to a vuex variable, have the navigation use a computed property that reads that vuex variable. If you have a lot more than this to do you might also consider a library that synchronizes vue router with vuex.
I had the same issue. I solved it by moving my logic to navigation guards (https://next.router.vuejs.org/guide/advanced/navigation-guards.html#global-before-guards)
For example:
const routes = [
{
path: '/',
name: 'Home',
beforeEnter:async() => {
let loggedIn = await store.checkIfLoggedIn()
if (loggedIn) router.push({name:'Dashboard'})
return true
},
component: () => import('../views/Home.vue')
},
{
path: '/dashboard',
name: 'Dashboard',
beforeEnter:async() => {
let loggedIn = await store.checkIfLoggedIn()
if (!loggedIn) {
router.push({name:'Home'})
}
return true
}]

I have a route component, why are my props not automatically updating when I set them in the route definition?

I have my index book that list all the registered books and when I click to edit a specif book it does get the specif book's id in the route but my props element does not get it, what gives an error!
How can I fix it?
Below I have the code on my index page:
<router-link :to="{ name: 'update_book', params: {id: book.id} }">
<font-awesome-icon icon="pen-square" />
</router-link>
In my update page I have:
<script>
props: ['id'],
data() {
return {
books: [],
};
},
methods: {
getBook(id) {
axios.get(`http://localhost:3000/api/v1/books/${id}`) // Gets an specif book
.then((response) => { this.books = response.data; });
},
created() {
this.getBook(this.id);
},
watch: {
$route() {
this.getBook(this.id);
},
Router do not pass id to props.In your case you can find id in this.$route.params
Even if you use something like /book/:id in router itself, that id param will live in this.$route.params.id.
So you need something like :
created() {
this.getBook(this.$router.params.id);
},
And btw, in watcher too.

Vuejs: pass in an array of hashes to prop

This is probably a trivial question but I haven't figured out how to get this working. I am trying to pass an array of hashes as a prop to another component in my Vue.js project.
My code looks something like this:
Sidebar.vue
<template>
<b-nav vertical>
<b-nav-item v-for='nav in items' :key='nav.title' :to='nav.url'>
{{nav.title}}
</b-nav-item>
</b-nav>
</template>
<script>
export default {
props: {
items: {
type: Array,
default: () => []
}
}
}
</script>
And I am calling this code as such:
<template>
...
<sidebar :items="myItems"/>
...
</template>
<script>
import Sidebar from '~/components/Sidebar.vue'
export default {
components: {
Sidebar
},
data: () => {
return {
myItems: [
{
title: 'Link 1',
url: '/link1'
},
{
title: 'Link 2',
url: '/link2'
},
{
title: 'Link 3',
url: '/link4'
},
{
title: 'Link 4',
url: '/link4'
}
]
}
}
}
</script>
However, nothing is appearing on the page.
How can I pass the array of hashes as a prop to my Sidebar component?
Thanks in advance!
You should change the arrow function data: () => { to data() {
According to the documentation:
Note that you should not use an arrow function with the data property (e.g. data: () => { return { a: this.myProp }}). The reason is arrow functions bind the parent context, so this will not be the Vue instance as you expect and this.myProp will be undefined.

Passing props to Vue.js components instantiated by Vue-router

Suppose I have a Vue.js component like this:
var Bar = Vue.extend({
props: ['my-props'],
template: '<p>This is bar!</p>'
});
And I want to use it when some route in vue-router is matched like this:
router.map({
'/bar': {
component: Bar
}
});
Normally in order to pass 'myProps' to the component I would do something like this:
Vue.component('my-bar', Bar);
and in the html:
<my-bar my-props="hello!"></my-bar>
In this case, the router is drawing automatically the component in the router-view element when the route is matched.
My question is, in this case, how can I pass the the props to the component?
<router-view :some-value-to-pass="localValue"></router-view>
and in your components just add prop:
props: {
someValueToPass: String
},
vue-router will match prop in component
sadly non of the prev solutions actually answers the question so here is a one from quora
basically the part that docs doesn't explain well is
When props is set to true, the route.params will be set as the component props.
so what you actually need when sending the prop through the route is to assign it to the params key ex
this.$router.push({
name: 'Home',
params: {
theme: 'dark'
}
})
so the full example would be
// component
const User = {
props: ['test'],
template: '<div>User {{ test }}</div>'
}
// router
new VueRouter({
routes: [
{
path: '/user',
component: User,
name: 'user',
props: true
}
]
})
// usage
this.$router.push({
name: 'user',
params: {
test: 'hello there' // or anything you want
}
})
In the router,
const router = new VueRouter({
routes: [
{ path: 'YOUR__PATH', component: Bar, props: { authorName: 'Robert' } }
]
})
And inside the <Bar /> component,
var Bar = Vue.extend({
props: ['authorName'],
template: '<p>Hey, {{ authorName }}</p>'
});
This question is old, so I'm not sure if Function mode existed at the time the question was asked, but it can be used to pass only the correct props. It is only called on route changes, but all the Vue reactivity rules apply with whatever you pass if it is reactive data already.
// Router config:
components: {
default: Component0,
named1: Component1
},
props: {
default: (route) => {
// <router-view :prop1="$store.importantCollection"/>
return {
prop1: store.importantCollection
}
},
named1: function(route) {
// <router-view :anotherProp="$store.otherData"/>
return {
anotherProp: store.otherData
}
},
}
Note that this only works if your prop function is scoped so it can see the data you want to pass. The route argument provides no references to the Vue instance, Vuex, or VueRouter. Also, the named1 example demonstrates that this is not bound to any instance either. This appears to be by design, so the state is only defined by the URL. Because of these issues, it could be better to use named views that receive the correct props in the markup and let the router toggle them.
// Router config:
components:
{
default: Component0,
named1: Component1
}
<!-- Markup -->
<router-view name="default" :prop1="$store.importantCollection"/>
<router-view name="named1" :anotherProp="$store.otherData"/>
With this approach, your markup declares the intent of which views are possible and sets them up, but the router decides which ones to activate.
const User = {
props: ['id'],
template: '<div>User {{ id }}</div>'
}
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User, props: true }
// for routes with named views, you have to define the props option for each named view:
{
path: '/user/:id',
components: { default: User, sidebar: Sidebar },
props: { default: true, sidebar: false }
}
]
})
Object mode
const router = new VueRouter({
routes: [
{ path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } }
]
})
That is the official answer.
link
Use:
this.$route.MY_PROP
to get a route prop