Vue Router with Boolean Query Parameter - javascript

Problem: I have a component that needs a boolean value optionally passed to it as part of a call from within the view app and from an external app. When I invoke the router directly I can pass the boolean with no issues but if I route by using the actual URL I get a parse warning. To prevent the warning should I be using a string instead and parse it myself?
Router:
export default new Router({
routes: [
{
path: '/foo',
name: 'Foo',
component: Foo,
props: (route) => ({ booleanParam: route.query.booleanParam })
}
]
})
Component:
<template>
<div>
BooleanParam: {{booleanParam}}
</div>
</template>
<script>
export default {
name: 'Foo',
props: {
booleanParam: {
type: Boolean,
required: false
}
}
}
</script>
Works:
router.push( { name: 'Foo', query: { booleanParam: true } })
Generates Warning:
http://localhost:8080/foo?booleanParam=true
Warning:
[Vue warn]: Invalid prop: type check failed for prop "booleanParam".
Expected Boolean, got String.

If a boolean is required by the component then parse the value as a Boolean before setting this as a prop:
props: (route) => ({ booleanParam: (route.query.booleanParam === 'true') })
This way the correct type is ensured.
EDIT:
As noted in the comment by the OP to support both String and Boolean the parameter could be converted to String to ensure both types work:
props: (route) => ({ booleanParam: (String(route.query.booleanParam). toLowerCase() === 'true') })

have you try this
const router = new VueRouter({
routes: [
{
path: '/foo',
name:"Foo"
component: Foo, props: (route) => ({ query: route.query.q }) }
]
})
OR
{path:'/foo/:booleanParam', name:'Foo', component: Foo }

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',...]
...
}

How to retrieve data from vue component in another component?

There is a vue royter
.....
const Edit = Vue.component('edit', require('./components/pages/edit.vue'));
const Product_category = Vue.component('home', require('./components/pages/product_categories.vue'));
const routes = [
........
{
path: '/product_categories',
name: 'product_categories',
component: Product_category
},
{
path: '/product_categories/edit/:id',
name: 'product_categories_edit',
components: {default: Edit, entity: Product_category},
props: {default: true, entity: true}
}
];
How can I get data in component Product_category componate Edit?
<script>
export default {
props: ['id', 'entity'],
mounted: function () {
console.log('Admin edit page mounted.');
console.log(this.entity); // Eror
console.log(entity); // Eror
this.getData();
},
}
</script>
A direct appeal is not suitable, because each router will have its own entity.
Use vuex if you prefer a global state-object. It's properties can be mapped to each instance and component https://github.com/vuejs/vuex
If you prefer an event based approach use an event bus https://alligator.io/vuejs/global-event-bus/
It is all well described at multiple positions in the official vuejs documentation.

Categories

Resources