I got a problem with optional route params, that route param (id) is lost when I access the child component
this is my route config on the router
{
path: "route/:id?",
component: () => import("*****"),
props: true,
children: [
{
path: "/",
redirect: { name: "*****" }
},
{
path: "information",
component: () => import("****")
},
]
},
this is my route expected companies/1/description etc
is there something wrong with my code?
this is how I push the router
it shows success like that companies/1/information but if i go through to another child route.. this param is lost like companies/direction
If I understand it correctly you expect the <router-link> placed inside your Company component to somehow "inherit" route params from the current route automatically.
Unfortunately this is not how it works with optional params - it would work with non-optional params but optional params must be passed explicitly...
:to="{ name: link.routeName, params: { id: $route.params.id } }"
const companies = Vue.component('companies', {
template: `
<div id="app">
<router-link to="/companies/1">Company 1</router-link>
<router-link to="/companies/2">Company 2</router-link>
<router-view></router-view>
</div>
`
})
const company = Vue.component('company', {
props: ['id'],
template: `
<div id="app">
<h4> {{ id }} </h4>
<h4> {{ $route.fullPath }} </h4>
<router-link :to="{ name: 'adminBusinessProfileInformation', params: { id: $route.params.id } }">Information</router-link>
<router-link :to="{ name: 'adminBusinessProfileDescription', params: { id: $route.params.id } }">Description</router-link>
<router-view></router-view>
</div>
`
})
const child = Vue.component('child', {
template: `
<div>
Child component
</div>
`
})
const router = new VueRouter({
mode: 'history',
routes: [{
path: '/',
redirect: 'companies'
},
{
name: 'companies',
path: '/companies',
component: companies
},
{
path: '/companies/:id',
component: company,
props: true,
children: [{
path: "/",
redirect: {
name: "adminBusinessProfileInformation"
}
},
{
path: "information",
component: child,
name: "adminBusinessProfileInformation"
},
{
path: "description",
component: child,
name: "adminBusinessProfileDescription"
}
]
}
]
})
new Vue({
el: '#app',
router,
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<router-link to="/companies/1">Company 1</router-link>
<router-link to="/companies/2">Company 2</router-link>
<router-view></router-view>
</div>
Related
I am new to Vuejs, I am looking to make my code effective just by having one vue component, and i want to specify the routing only once.
Currently i have one info.vue in a apps directive and prises.vue & priseshigh.vue in more directive. I want to have just one component in more directive. But the problem is in info.vue i have used two buttons, each button routes to prises.vue & priseshigh.vue respectively. Just like below code:
<vs-button class="btn" #click="$router.push({name: 'prises'}).catch(err => {})" >Go To</vs-button>
<vs-button class="btn" #click="$router.push({name: 'priseshigh'}).catch(err => {})" >Go There</vs-button>
My first question: So now i want to know, if i make one component as prisescomplete.vue by combining prises.vue & priseshigh.vue, how do i specify the routing to the buttons respectively in info.vue And what should i use in the prisescomplete.vue component to route the prises.vue & priseshigh.vue contents respectively .
My second question: below is my routing.js, so now what changes should i make in routing if i just have one component in views directive, and also with respect to first question.
{
path: '/apps/info',
name: 'info',
component: () => import('./views/apps/info/Info.vue'),
meta: {
rule: 'editor',
no_scroll: true
}
},
{
path: '/apps/info/info-more/prises-card',
name: 'prises',
component: () => import('./views/apps/info/more/prises.vue'),
meta: {
pageTitle: 'info-more',
rule: 'editor',
no_scroll: true
}
},
{
path: '/apps/info/info-more/priseshigh-card',
name: 'priseshigh',
component: () => import('./views/apps/info/more/priseshigh.vue'),
meta: {
pageTitle: 'info-more',
rule: 'editor',
no_scroll: true
}
},
Please send me the modified code, so that i can understand it easily.
You could pass props to route components.
https://router.vuejs.org/guide/essentials/passing-props.html
{
path: '/apps/info/info-more/prises-card',
name: 'prises',
component: () => import('./views/apps/info/more/prisescomplete.vue'),
props: {
prisesType: "prises"
},
meta: {
rule: 'editor'
}
},
{
path: '/apps/info/info-more/priseshigh-card',
name: 'priseshigh',
component: () => import('./views/apps/info/more/prisescomplete.vue'),
props: {
prisesType: "priseshigh"
},
meta: {
rule: 'editor'
}
}
PrisesComplete.vue
<template>
<div>
<span v-if="prisesType === 'prises'"> Prises </span>
<span v-else-if="prisesType === 'priseshigh'"> Prises High </span>
</div>
</template>
<script>
export default {
name: "PrisesComplete",
props: {
prisesType: {
type: String,
required: true
}
}
}
</script>
Also, you could use to="/path"
https://router.vuejs.org/guide/essentials/named-routes.html
<vs-button class="btn" :to="{ name: 'prises' }"> Go To </vs-button>
<vs-button class="btn" :to="{ name: 'priseshigh' }"> Go There </vs-button>
First of all you need to write a navigation.vue component for the navigation and render inside app with routerview. Look the codesandbox and the describtion
TheNavigation.vue
<template>
<div>
<vs-button
class="btn"
#click="$router.push({ name: 'prises' }).catch((err) => {})"
>Prises</vs-button
>
<vs-button
class="btn"
#click="$router.push({ name: 'priseshigh' }).catch((err) => {})"
>Priseshigh</vs-button
>
</div>
</template>
then render the navigation bar with the router view for loading the router.Here is the
App.vue where you render the navigation and routerview.
<template>
<div id="app">
<TheNavigation/>
<hr>
<RouterView/>
</div>
</template>
<script>
import TheNavigation from "./components/TheNavigation";
export default {
name: "App",
components: {
TheNavigation
}
};
</script>
RouterView is reponsible for loading the components which are defined inside router.js
Here is the Router.js
import Vue from "vue";
import Router from "vue-router";
Vue.use(Router);
const router = new Router({
mode: "history",
routes: [
{
path: "/prises-card",
name: "prises",
component: () => import("./components/Prises.vue"),
meta: {
pageTitle: "info-more",
rule: "editor",
no_scroll: true
}
},
{
path: "/priseshigh-card",
name: "priseshigh",
component: () => import("./components/PrisesHigh.vue"),
meta: {
pageTitle: "info-more",
rule: "editor",
no_scroll: true
}
}
]
});
export default router;
I have some routes which are newly added. the sidebar is dynamically created based on links added to the routes.
I am able to print the route name in plain text but when assigned to the vue-route it simple gives localhost:8080 so where am i going wrong.
configroutes file:
const routes = [
{
path: 'create_schedule',
name: 'activate.create_schedule',
meta: {
_routeName: 'activate_create_schedule',
sectionName: 'Create Schedule'
},
component: createSchedule,
},
]
Main Routes File
import ConfigureRoutes from './configureRoutes.js';
const routes = [
...ConfigureRoutes,
];
export default routes;
export const getActivateConfigRoutes = function () {
return routes;
};
dashboard Component file
data() {
const configRoutes = getActivateConfigRoutes();
const sidebarRoutes = [
{
name: '/',
meta: {
sectionName: 'CONFIGURE'
},
redirect: {
name: 'activate.create_schedule'
},
children: [
...configRoutes
]
},
];
return {
sidebarRoutes
};
}
}
</script>
aside bar:
<aside class="menu">
<ul class="menu-list --campaign-sidebar">
<li class="main-section-menu" v-for="(sidebarRoute, index) in sidebarRoutes" :key="sidebarRoute.id">
<router-link :to="{ name: sidebarRoute.name, params: { campaign_id: currentCampaign.id }}" class="sidebar-link" active-class="is-active">
{{ sidebarRoute.meta.sectionName }}
</router-link>
<ul class="sub-menu-list" v-if="sidebarRoute.children.length > 0">
<li v-for="childRoute in sidebarRoute.children" :key="childRoute.id">
<router-link :to="{ name: childRoute.name , params: { campaign_id: currentCampaign.id }}" class="sidebar-sub-link" active-class="is-active-submenu router-link-active">
{{ childRoute.meta.sectionName }} {{ childRoute.name }}
</router-link></li>
</ul>
<span class="base" v-if="((sidebarRoutes.length - 1) === index)"></span>
</li>
</ul>
</aside>
you can see what when I try to print childRoute.name, it gives me the name and so that data is passed properly to the loop. then what is the issue here ? can someone help on the same ?
[vue-router] Route with name 'activate.create_schedule' does not exist vue-router.esm.js:16
I add to my routes file path with children:
path: '/warehouse/:id',
name: 'ShowWarehouse',
component: ShowWarehouse,
children: [{
path: 'edit',
name: 'EditWarehouse',
component: EditWarehouse
}
]
Now in component ShowWarehouse I have:
<div v-if="!changeEdit">
<div v-if="warehouseData">
<div>Name: {{ warehouseData.warehouse.name }}</div>
<div>
<router-link
:to="{ name: 'EditWarehouse', params: {id: warehouseData.warehouse.id }}"
>Edit</router-link>
</div>
</div>
</div>
<router-view v-else></router-view>
When the user click edit button I need load component EditWarehouse, but component ShowWarehouse must be disappear, and if user back (without /edit) disappear componet EditWarehouse and load component ShowWarehouse. I write method in watch:
watch: {
$route() {
if (this.$route.path == '/warehouse/' + id_get_from_API + '/edit') {
this.changeEdit = true;
} else {
this.changeEdit = false;
}
}
},
The problem is when the user is at mydomain.com/warehouse/23/edit and click reload page (F5), then Vue loads component ShowWarehouse instead of loading EditWarehouse.
I using mode: 'history'.
Problem:
From the Vue.JS website: "Vue does provide a more generic way to observe and react to data changes on a Vue instance: watch properties." When you refresh the page the watch() method will not be executed because it is a new Vue instance and no data has changed on the Vue instance yet. You should probably use a different pattern to determine which component to show. (https://v2.vuejs.org/v2/guide/computed.html#Computed-vs-Watched-Property)
Solution:
I suggest making the EditWarehouse a sibling route to ShowWarehouse, and make EditWarehouse its own component (you already have this). Your router-link in the ShowWarehouse component can stay the same.
Code Snippet:
const ShowWarehouse = {
template: `<div><h1>ShowWarehouse</h1> <div v-if="warehouseData">
<div>Name: {{ warehouseData.warehouse.name }}</div>
<div>ID: {{ $route.params.id }}</div>
<div>
<router-link :to="{ name: 'EditWarehouse'}">Edit</router-link>
</div>
</div></div>`,
computed: {
warehouseData: function() {
let data;
let id = this.$route.params.id;
if (id) {
data = {
warehouse: {
name: 'Some Warehouse Name',
id: id
}
}
}
return data;
}
}
};
const EditWarehouse = {
template: "<h1>EditWarehouse [{{ $route.params.id }}]</h1>"
}
const router = new VueRouter({
routes: [{
path: '/warehouse/:id',
name: 'ShowWarehouse',
component: ShowWarehouse
},
{
path: '/warehouse/:id/edit',
name: 'EditWarehouse',
component: EditWarehouse
}
]
});
new Vue({
el: '#app',
router
});
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<p>
<router-link :to="{ name: 'ShowWarehouse', params: { id: 123 }}">Go to Warehouse 123</router-link>
</p>
<router-view/>
</div>
Here is a jsfiddle with the same code:
https://jsfiddle.net/austinwasinger/oruswb3a/39/
I'm using Vue CLI 3 and it makes a few routes. One is Home.vue. In my program I am trying to programmaticaly go to different pages. I added the routes I need in router.js but kept the already created routes for Home.vue and About.vue. It works fine until I get to 'Home' and get a warning: [vue-router] Route with name 'Home' does not exist.'
Here is the code:
<template>
<div class='secondItem'>
<h4 v-for="item in menuItems"
#click="bindMe(item)" v-bind:class="{'active':(item === current)}">{{item}}</h4>
</div>
</template>
<script>
export default {
name: 'Header',
data() {
return {
current: '',
menuItems: ['Home', 'About', 'Portfolio', 'Contact'],
}
},
methods: {
bindMe(item) {
this.current = item;
this.$router.push({
path: item
})
}
}
}
<script>
Are you using named routes? In that case you need to use name instead of path:
this.$router.push({
name: item
})
Also, your example can be simplified quite a lot. Try this:
<template>
<div class="secondItem">
<router-link :to="{ name: item }" tag="h4" active-class="active" v-for="item in menuItems" v-bind:key="item">{{item}}</router-link>
</div>
</template>
<script>
export default {
name: 'Header',
data() {
return {
menuItems: ['Home', 'About', 'Portfolio', 'Contact']
}
}
}
<script>
I'm trying to figure out how child routes in VueJS work. I would think that if I had a news overview with links to each news item, I could then use a child route to view the news item, but it doesn't works as I expects.
Is it me that is doing it wrong or?
const router = new VueRouter({
routes: [
{
path: '/news',
name: 'news',
component: News,
children: [
{
path: ':id',
name: 'newsitem',
component: Newsitem
}
]
}
]
});
I have created a jsfiddle to show how I would expect it to work.
If I uncomment the router in the javascript, then it works fine, but not with children.
Like Moersing.Lin said you forgot to put a <router-view> in your News Component.
Here is an working example of your fiddle:
const News = {
template: `<div>
<h1>News</h1>
<br><br>
<router-view></router-view>
</div>
`
}
const Newsitem = {
template: "<h2>News {{this.$route.params.id}}</h2>"
}
const router = new VueRouter({
routes: [{
path: '/news',
name: 'news',
component: News,
children: [{
path: ':id',
name: 'newsitem',
component: Newsitem,
}]
}]
});
new Vue({
el: '#app',
router,
}).mount('#app');
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<ul>
<li>
<router-link :to="{ name: 'news'}">News list</router-link>
</li>
<li>
<router-link :to="{ name: 'newsitem', params: { id: 'item-1' }}">Item 1</router-link>
</li>
<li>
<router-link :to="{ name: 'newsitem', params: { id: 'item-2' }}">Item 2</router-link>
</li>
</ul>
<router-view></router-view>
</div>
I got it, A Vue Router is required <router-view></router-view>,but in your code, The root component is there, but you forgot the parent,it needs a <router-view></router-view> too.
https://jsfiddle.net/v28yw3g5/
const News = {
template: `<div>
<h1>News</h1>
<br><br>
<router-view></router-view>
</div>
`
}
const Newsitem = {
template: "<h2>News {{this.$route.params.id}}</h2>"
}
const router = new VueRouter({
routes: [{
path: '/news',
name: 'news',
component: News,
children: [{
path: ':id',
name: 'newsitem',
component: Newsitem,
}]
}]
});
new Vue({
el: '#app',
router,
}).mount('#app');
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<ul>
<li>
<router-link :to="{ name: 'news'}">News list</router-link>
</li>
<li>
<router-link :to="{ name: 'newsitem', params: { id: 'item-1' }}">Item 1</router-link>
</li>
<li>
<router-link :to="{ name: 'newsitem', params: { id: 'item-2' }}">Item 2</router-link>
</li>
</ul>
<router-view></router-view>
</div>