Using vuejs2 & vue-router3, how do I take query parameters and pass them into the props of a route component? And remove the query string from the URL?
This is to support opening a link in a new window
const router = new Router({
routes: [
{
path: "/",
name: "dashboard",
meta: {
title: "",
roles: ["*"]
},
component: DashboardView,
props: AddQueryToPropsAndRemoveQuery
}
]
});
function AddQueryToPropsAndRemoveQuery(route) {
var props = route.params;
if (Object.entries(route.query).length > 0) {
// combine query params into the props
for (const [key, value] of Object.entries(route.query)) {
props[key] = value;
}
router.push({ params: props, query: undefined })
}
return props;
}
export default router;
Related
I would like to pass data with vue router from App.vue to view (Home).
Orignial data store in data() App.vuejs and I need to pass this data to view with methods passLanguage().
router
{
path: '/',
name: 'home',
component: HomeView,
props: true
},
app vue
export default {
data () {
return {
cons: 'true'
}
},
methods: {
passLanguage () {
this.$router.push({ name: 'home', params: { data: this.cons } })
}
}
}
Home vue
created () {
this.language = this.$route.params.data
}
Error returned
Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location: "/".
Consider using query params:
app
this.$router.push({ name: 'home', query: { cons: this.cons } })
home
created () {
this.language = this.$route.query.cons
}
I have a component, which has programmatic routing based on external data.
The external data is fetched in the App.vue component and used in child components as props.
The data is used in the child component like this:
props: {
externalData: Array
},
computed() {
data() {
return this.externalData
}
}
Here is my router.js (excerpt)
const routes = [
{
path: "/:hae?",
name: "Home",
component: Home
},
{
path: "*",
name: "NotFound",
component: NotFound
}
];
And my Home.vue with the $router.push method (excerpt):
created() {
if (this.$route.path === "/") {
this.$router.push({
params: {
hae: this.data[0].id
}
});
}
},
So here is what i want to achieve:
This is my example array: [{hae: "hae001"}, {hae: "hae002"}, {hae: "hae003"} ...]
When you navigate to https://website.com/ i want the router to redirect you to a param which is the first element of the array, but if you navigate to somewhere else which is not existing in the array (e.g. /something) i want the router to render my NotFound.vue component.
What am i missing?
created() {
const firstDataElementExists = this.data && this.data[0] && this.data[0].hae
if (!firstDataElementExists) {
this.$router.push('/404')
return
}
const isRootPath = this.$route.path === '/'
if (isRootPath) {
this.$router.push(this.data[0].hae)
return
}
const pathIsInData = !!this.data.find(d => d.hae === p)
if (!isRootPath && !pathIsInData) {
this.$router.push('/404')
}
}
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);
}
}
I have a vue-router like this
import Vue from 'vue';
import Router from 'vue-router';
import http from './helpers/http';
import Home from './views/Home/Home.vue';
import HomeMentor from './views/Home/HomeMentor.vue';
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: '',
component: () => import(/* webpackChunkName: "Container" */ './components/Container.vue'),
children: [
{
path: '/',
name: 'Dashboard',
component: {
render(c) {
http.request('GET', '/profile').then( async ({ data }) => {
console.log(data.profile.email)
if (data.profile.email === "vickysultan08#gmail.com") {
console.log('sip')
return c(HomeMentor);
} else {
return c(Home);
}
});
}
},
}
],
beforeEnter: isAuthentication,
}
});
The thing is, only the return component inside the conditional statement that cannot executed inside axios statement as the result below
While the return component inside the conditonal statement can be executed outside the axios statement like this
children: [
{
path: '/',
name: 'Dashboard',
component: {
render(c) {
a = 10
if (a === 10) {
console.log('sip')
return c(HomeMentor);
} else {
return c(Home);
}
}
},
}
],
I'm quite new in Vue JS and have to continue other person's code. Any advice?
Unfortunately, render functions must be synchronous.
What you may be able to do instead is simply use an async function to return the component, ala Async Components and Lazy Loading Routes.
const Dashboard = () => http.request('GET', '/profile').then(({ data }) => {
console.log('profile email', data.profile.email)
let isMentor = data.profile.email === 'vickysultan08#gmail.com'
let componentPath = `./views/Home/${isMentor ? 'HomeMentor' : 'Home'}.vue`
return import(componentPath) // chains in the "import" promise
})
and then in your route...
component: Dashboard,
If lazy-loading the component isn't working for you, you could always try pre-loading it
import http from './helpers/http';
import Home from './views/Home/Home.vue';
import HomeMentor from './views/Home/HomeMentor.vue';
const Dashboard = () => http.request('GET', '/profile').then(({ data }) => {
let isMentor = data.profile.email === 'vickysultan08#gmail.com'
return isMentor ? HomeMentor : Home
})
Using cue-cli 3. Is it possible to do this (router.js):
axios.get( `${process.env.VUE_APP_API_DOMAIN}/wp-json/api/v1/routes`).then( r => r.data ).then(routes => {
routes.pages.forEach( (e) => {
router.addRoutes([
{
path: `/${e.slug}`,
component: e.template,
},
]);
});
});
e.template is a string 'Default' and of course VueJS says:
route config "component" for path: /privacy-policy cannot be a string id. Use an actual component instead. Tried with Vue.component(e.template) no luck.
What I want to do here is create dynamic routes based on XHR response.
Here is all router.js code:
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import Default from './views/Default.vue'
import Test from './views/Test.vue'
import axios from "axios";
Vue.use(Router);
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: Home
},
]
});
axios.get( `${process.env.VUE_APP_API_DOMAIN}/wp-json/api/v1/routes`).then( r => r.data ).then(routes => {
routes.pages.forEach( (e) => {
router.addRoutes([
{
path: `/${e.slug}`,
component: e.template,
},
]);
});
});
export default router;
Currently I ended up with this solution:
function getComponent(name) {
let component = null;
switch(name)
{
case 'Default':
component = Default;
break;
case 'Test':
component = Test;
break;
}
return component;
}
axios.get( `${process.env.VUE_APP_API_DOMAIN}/wp-json/api/v1/routes`).then( r => r.data ).then(routes => {
routes.pages.forEach( (e) => {
router.addRoutes([
{
path: `/${e.slug}`,
component: getComponent(e.template),
},
]);
});
});
Another one more cleaner solution:
const components = { Default, Test }
axios.get( `${process.env.VUE_APP_API_DOMAIN}/wp-json/api/v1/routes`).then( r => r.data ).then(routes => {
routes.pages.forEach( (e) => {
router.addRoutes([
{
path: `/${e.slug}`,
component: components[e.template],
},
]);
});
});
If e.template stores the template string,
You should wrap it as one options object like {template: e.template, props: {}, data: function () {} }, then call Vue.extend to construct the component.
or you can ignore Vue.extend because Vue will call Vue.extend to construct the component automatically.
Check the usage at Vue Guide: Vue.component
Edit as the OP states e.tempate is one component name:
if e.template is the name of component, uses Vue.component(e.template).
Vue.config.productionTip = false
const router = new VueRouter({
routes: [
]
})
Vue.component('test', {
template: '<div>I am Predefined component -> {{index}}</div>',
props: ['index']
})
let routerIndex = 1
setInterval(()=> {
let newComponent = routerIndex%2 ? {template: '<div>I am User -> {{index}}</div>', props: ['index']} : Vue.component('test')
router.addRoutes([{
path: '/Test' + routerIndex,
name: 'Test' + routerIndex,
component: newComponent,
props: { index: routerIndex }
}])
console.log('add route = ', '/Test' + routerIndex, ' by ', routerIndex%2 ? 'options object' : 'Vue.component')
routerIndex++
}, 2000)
Vue.use(VueRouter)
app = new Vue({
el: "#app",
router,
data: {
routeIndex: 0
},
watch: {
routeIndex: function (newVal) {
this.$router.push({'name': 'Test'+newVal})
}
}
})
div.as-console-wrapper {
height: 100px;
}
<script src="https://unpkg.com/vue#2.5.16/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<p>Current Route Index: {{routeIndex}}</p>
Test Route: <input v-model="routeIndex" type="number">
<router-view></router-view>
</div>