How can I pass a variable when calling a route? - javascript

I want to display the customer's name in a new vue page(from Messages.vue to CustomerMessages.vue). I don't know how to pass this variable into the child vue.
I have tried props but it doesn't work as I expected.
{ path: '/messages/:id/customers', component: CustomerMessages, name: 'CustomerMessage', beforeEnter: requireAuth }
this.$router.push({ name: 'CustomerMessage', params: { id: item.ID }, data: {name: this.customers.FullName} })
{{name}}
props:{
name: ''
}

Vue-router doesn't let you pass arbitrary data to routes like that.
If you want a parent component to share some data with a child route, then you can just bind it on the <router-view> component like you would with any other component prop.
Parent
<router-view :name="name"></router-view>
data() {
return {
name: 'Alice'
}
}
Child
{{ name }}
props: ['name']

Related

How to get a specific child component object property from parent component?

I would like to grab a child component's "meta" property from parent. Is it possible somehow ?
I know there is a solution with an emit method, but is there some easier way to make it happen ?
// Default.vue <-- parent component
<template>
<h1>{{ pagetitle }}</h1>
<router-view />
</template>
<script>
import { defineComponent } from 'vue'
export default defineComponent({
name: 'LayoutDefault',
computed: {
pagetitle () {
let title = this.$route.meta.title // <--- I want to access child's component meta here
// if title not provided, set to empty string
if (!title) title = ''
return title
}
}
})
</script>
// router/routes.js
const routes = [
{
path: '/',
component: () => import('layouts/Default.vue'),
children: [
{
path: 'dashboard',
name: 'dashboard',
meta: { title: 'Dashboard', auth: true, fullscreen: false }, // <--- TAKE THIS
component: () => import('pages/dashboard.vue')
}
]
}
]
// pages/dashboard.vue <-- child component
<template>
<div>
dashboard content
</div>
</template>
<script>
import { defineComponent } from 'vue'
export default defineComponent({
name: 'Dashboard',
meta: { // <--- this should be reachable from the parent component (Default.vue)
title: 'Dashboard',
auth: true,
fullscreen: false
}
})
</script>
You can get component info via $route.matched.
Here's a PoC:
const Dashboard = Vue.defineComponent({
template: "<div>Some dashboard</div>",
meta: { title: "Dashboard" },
})
const router = new VueRouter({
routes: [{ path: "/", component: Dashboard }],
})
const app = new Vue({
router,
computed: {
// Note that this takes the *last* matched component, since there could be a multiple ones
childComponent: (vm) => vm.$route.matched.at(-1).components.default,
},
}).$mount('#app')
<div id="app">
<h1>{{ childComponent.meta.title }}</h1>
<router-view />
</div>
<script src="https://unpkg.com/vue#2/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router#3/dist/vue-router.js"></script>
As suggested by Estus Flash in a comment, instead of taking the last matched component we can take the last matched component that has meta defined. To do that, replace the following:
vm.$route.matched.at(-1).components.default
with:
vm.$route.matched.findLast((r) => "meta" in r.components.default)
.components.default
Some approaches I could figure from the web:
Using ref by this.$refs.REF_NAME.$data (As done here: https://stackoverflow.com/a/63872783/16045352)
Vuex or duplicating the logic behind stores (As done here: https://stackoverflow.com/a/40411389/16045352)
Source: VueJS access child component's data from parent

How to get query params in Vue.js 3 setup?

I want to make search page which after I click its button will be redirected to another page. And this page will be like this
http://localhost:8080/search?q=foo
and my router index.js looks like this
const routers = [
{
path: '/search',
name: 'Search',
component: SearchPage,
props: route => ( { query: route.query.q } )
}
]
and the question is how do i get the query value in target page SearchPage, in Vue.js 3?
This Answer is still confusing me, because not using composition API and not in vuejs 3
Using useRoute
You don't need to send the query as a prop. It's better to use useRoute because it's simpler and it can be accessed from any component, not just the page view component.
import { useRoute } from 'vue-router';
export default {
setup() {
const route = useRoute();
console.log(route.query);
}
}
Using a prop
First change the router mapping so that query maps to the query object:
props: route => ({ query: route.query })
In the destination component, SearchPage, create a query prop which will receive the query object from the router:
props: ['query']
And access it in setup via the props argument:
props: ['query'],
setup(props) {
console.log(props.query.q);
console.log(props.query.status);
}
another setup you can try, send propname by url
{ path: '/search/:propname', name: 'Search', component: SearchPage, props: true },
and on searchpage, on created() you can get recive it
this.$route.params.propname
For Vue Router 4 :: Compositon API :: Vue3
Router-link attach params
<router-link
style="width: 100%"
class="btn btn-success btn-block edit"
:to="{ name: 'editUser',params: {id: user.id}}">
<i class="fa-solid fa-user-gear"></i>
</router-link>
In a page you are receiving,
<script>
export default {
props: ["id"],
setup(props, context) {
console.log(props.id);
},
};
</script>
In Your app.js
import { createApp } from 'vue';
...
...
const app = createApp(root);
app.use(router);
router.isReady().then(() => {
app.mount('#app');
})

Vue - pass prop via router to component

I have a component with the object "project_element" and I want to transfer the object to another component through the "vue-router".
This is the code from my first component which opens the second component if the user clicks on the button.
<router-link :to="{ name: 'project', params: { project_url: project_element.project_name, project_element: project_element} }">
<b-button> Open </b-button>
</router-link>
This is the code from my Vue Router in index.js
{
path: '/projects/:project_url',
component: SingleProjectViewApp,
name: 'project',
props: { project_element: project_element }
},
I already managed to set the "project_element.project_name" to the url but I also need the "project_element" itself in my second component.
In the compenent I have set the object in the "props section"
props: {
project_element: {
type: Object,
required: true
}
},
The problem is in the Vue Router, I can't pass the project_element like a variable, only with quotation marks. But then I get an error because obviously the component expected an object and not a string.
Thanks for your help!
Try this in your router
path: '/projects/:project_url?',
component: SingleProjectViewApp,
props(route) {
const props = {
projectElement: route.params.project_url
};
return props;
}
and in your props change "project_element" to "projectElement" (generally you want to do camel case in vue props)
props: {
projectElement: {
type: Object,
required: true
}
},
The first thing that came to my mind is JSON.stringify() and JSON.parse(). Although I am not sure this is a perfect solution.
Any way try this:
<router-link :to="{ name: 'project', params: { project_url: project_element.project_name, project_element: JSON.stringify(project_element)} }">
<b-button> Open </b-button>
</router-link>
// router.js
{
path: '/projects/:project_url',
component: SingleProjectViewApp,
name: 'project',
props(route) {
return {
project_element: JSON.parse(route.params.project_element),
}
}
},
Note: I honestly think this is an antipattern and you should use different aproach for comunicating through components. custom-events, centralized-state, event-bus or even provide & inject will all be better for that kind of work.
routes: [
{
path: '/',
name: 'start',
component: Start,
meta: {
my_data: "my data here",
},
},]
to get data inside the component
this.$route.currentRoute.meta.my_data
UPDATE
this.$route.push("/"+ JSON.stringify(data) )
routes: [
{
path: '/:data',
name: 'start',
component: Start,
},]
to get data inside the component
JSON.parse(this.$route.params.data)

Passing props from one component to another when the transition happens using router.push

I currently have a Vue.js component called Summoner.vue which is rendered thanks to the router when a user visits the following URL - http://localhost:8080/summoner/username
In that component I have a <div> element which triggers a method on click, that sends the user to a new URL - http://localhost:8080/summoner/username/match/4132479262 which renders a different component Match.vue. Like this:
<div #click='specificMatch(match.gameId)'>
specificMatch(gameId){
router.push('/summoner/' + this.summoner + '/match/' + gameId)
}
Now all I want to do is pass an object as props from the first component to the second one, but I'm not sure how to do that because I'm using the router. Normally I'd pass props like this - <summoner v-bind:match="match.id"></summoner> but I guess that doesn't work in my case since I'm using router.
And these are my routes:
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/summoner/:summonerName',
name: 'summoner',
component: Summoner
},
{
path: '/summoner/:summonerName/match/:matchId',
name: 'match',
component: Match
}
]
})
Here is how you can do it with vue-router props :
{
path: '/summoner/:summonerName',
name: 'summoner',
component: Summoner,
props : true // now you can pass props to this route
}
then when you want to navigate to it :
this.$router.push({ name : summoner , params : { summonerName : this.summoner , somedata : 'hello' etc ... }})
now summoner component will have access to all these params on its props :
// summoner.vue
export default {
props : ['somedata',...]
...
}

VueJS component display and pass item to component

I am using VueJS 2.0 and vue-router 2 and am trying to show a template based on route parameters. I am using one view (WidgetView) and changing components displayed in that view. Initially I show a widget list component (WidgetComponent), then when the used selects a widget or the new button in in the WidgetComponent in the WidgetView I want to swap the WidgetComponent out and display the WidgetDetails component, and pass information to that component:
WidgetComponent.vue:
<template>
...
<router-link :to="{ path: '/widget_view', params: { widgetId: 'new' } }"><a> New Widget</a></router-link>
<router-link :to="{ path: '/widget_view', params: { widgetId: widget.id } }"><span>{{widget.name}}</span></router-link>
</template>
<script>
export default {
name: 'WidgetComponent',
data() {
return {
widgets: [{ id: 1,
name: 'widgetX',
type: 'catcher'
}]}
}
}
</script>
WidgetView.vue
<template>
<component :is="activeComponent"></component>
</template>
<script>
import WidgetComponent from './components/WidgetComponent'
import WidgetDetail from './components/WidgetDetail'
export default {
name: 'WidgetView',
components: {
WidgetComponent,
WidgetDetail
},
mounted: function () {
const widgetId = this.$route.params.widgetId
if (widgetId === 'new') {
// I want to pass the id to this component but don't know how
this.activeComponent = 'widget-detail'
}
else if (widgetId > 0) {
// I want to pass the id to this component but don't know how
this.activeComponent = 'widget-detail'
}
},
watch: {
'$route': function () {
if (this.$route.params.widgetId === 'new') {
// how to pass id to this compent?
this.activeComponent = 'widget-detail'
}
else if (this.$route.params.widgetId > 0){
// how to pass id to this compent?
this.activeComponent = 'widget-detail'
}
else {
this.activeComponent = 'widget-component'
}
}
},
data () {
return {
activeComponent: 'widget-component',
widgetId: 0
}
}
}
</script>
WidgetDetail.vue
<template>
<option v-for="manufacturer in manufacturers" >
{{ manufacturer.name }}
</option>
</template>
<script>
export default {
props: ['sourcesId'],
...etc...
}
</script>
router.js
Vue.use(Router)
export default new Router({
routes: [
{
path: '/widget_view',
component: WidgetView,
subRoutes: {
path: '/new',
component: WidgetDetail
}
},
{
path: '/widget_view/:widgetId',
component: WidgetView
},
]
})
I couldnt get route paramers working but I managed to get routes working by hard coding the route ie
<router-link :to="{ path: '/widget_view/'+ 'new' }"> New Widget</router-link>
But I dont know how to pass an id to the given template from the script (not template) code in WidgetView.
Here is a basic example http://jsfiddle.net/ognc78e7/1/. Try using the router-view element hold your components. Also, use props inside components to pass in variables from the URL. The docs explain it much better http://router.vuejs.org/en/essentials/passing-props.html
//routes
{ path: '/foo/:id', component: Bar, props:true }
//component
const Bar = { template: '<div>The id is {{id}}</div>',props:['id'] }
Not sure which way you want it, but you could have the /foo/ path actually be the creation widget and then have the dynamic /foo/:id path. Or you could do like I did here and the foo path is like a start page that links to different things.

Categories

Resources