Vue.js nested routing - javascript

My Current Route is
function route(path, view) {
return {
path: path,
meta: meta[path],
component: resolve => import(`pages/${view}View.vue`).then(resolve)
}
}
route('/', 'Home'),
route('/help', 'Help),
route('/blog', 'BlogList'),
route('/blog/:slug', 'BlogDetails'),
Now Everything is working fine. but when I visit /blog/:slug route and from that component when I click back to /help from button Route pattern is /blog/help not the /help.

See my jsfiddle Vuejs route , I mean this help you.
const Home = {
template: '<h1>Home</h1>'
};
const Help = {
template: '<h1>Help</h1>'
};
const Profile = {
template: '<h1>Profile</h1>'
};
const User = {
template: '<h1>User</h1>'
};
routes = [
{path: '/', component: Home},
{path: '/help', component: Help},
{path: '/user', component: User},
{path: '/user/:id', component: {
render(h) {
return h(
'h1',
{ style: {color: 'skyblue'} },
`User id: ${this.$route.params.id}`
);
}
}}
];
const router = new VueRouter({
routes
});
new Vue({
router
}).$mount('#app');
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<router-link :to='{path: "/"}'>/</router-link> <br>
<router-link :to='{path: "/help"}'>/help</router-link> <br>
<router-link :to='{path: "/user"}'>/user</router-link> <br>
<router-link :to='{path: "/user/userid"}'>/user/userID</router-link>
{{$route.path}}
<router-view></router-view>
<br>
<button #click='$router.go(-1)'>go back</button>
<button #click='$router.go(1)'>go forward</button>
</div>

Related

My children paths in vue refuse to render their view when resolved, they are rendering the parent view

I've tried redoing the whole process, refactoring the code a bit (I'm still rather new to vue so some of my code is a bit sloppy) but nothing seems to render the component for the child path. It always resolves to the parent path.
The code in my products.js (all paths under products)
import Products from '../views/Products.vue'
import Product from '../views/Product.vue'
export default {
path: '/products',
name: 'Products',
component: Products,
children: [
{
path: ':id',
name: 'OneProduct',
component: Product
}
]
}
The code in my product.view (the view for the path: /products/:id)
<template>
<div>
<ExpandedProduct
:prodNmae="$route.query.productName"
:price="$route.query.prodPrice"
:description="$route.query.description"
/>
</div>
</template>
<script>
import ExpandedProduct from '../components/ExpandedProduct'
export default {
name: 'Product',
components: {
ExpandedProduct
}
}
</script>
<style lang="scss" scoped>
</style>
the ExpandedProduct component is the component which is supposed to be rendered when the route resolves to '/products/:id'
ExpandedProduct.vue
<template>
<div>
<div class="carousel-holder">
<v-carousel>
<v-carousel-item
v-for="(item,i) in items"
:key="i"
:src="item.src"
reverse-transition="fade-transition"
transition="fade-transition"
></v-carousel-item>
</v-carousel>
</div>
<div class="description-holder">
<h2>{{ $route.query }}</h2>
<h4>{{ $route.query.prodPrice }}</h4>
<h3>{{ $route.query.description }}</h3>
</div>
</div>
</template>
<script>
export default {
name: 'ExpandedProduct',
props: {
prodName: {
type: String,
required: true,
default: 'N/A'
},
price: {
type: String,
required: true,
default: 'N/A'
},
description: {
type: String,
required: true,
default: 'N/A'
}
},
data () {
return {
items: [
{ src: 'https://cdn.vuetifyjs.com/images/carousel/squirrel.jpg' },
{ src: 'https://cdn.vuetifyjs.com/images/carousel/sky.jpg' },
{ src: 'https://cdn.vuetifyjs.com/images/carousel/bird.jpg' },
{ src: 'https://cdn.vuetifyjs.com/images/carousel/planet.jpg' }
]
}
}
}
</script>
<style lang="scss" scoped>
</style>
If someone could explain to me what I'm missing
Creating a /product route and a separate /product/:id route is not the same as adding children with :id to a parent /product route.
The former creates a page without the :id parameter and a page that handles the :id parameter. The latter creates ONE page and a child router-view gets the :id parameter.
I think it's better explained with snippets:
1. This is the /product + /product/:id
const Foo = {
template: `
<div>Foo</div>
`
}
const FooId = {
template: `
<div>Foo+{{ $route.params.id }}</div>
`
}
const Bar = {
template: `
<div>Bar</div>
`
}
const Baz = {
template: `
<div>Baz</div>
`
}
const routes = [{
path: '/foo',
component: Foo
},
{
path: '/foo/:id',
component: FooId
},
{
path: '/bar',
component: Bar
},
{
path: '/baz',
component: Baz
}
]
const router = new VueRouter({
routes
})
new Vue({
router,
el: "#app",
})
div {
border: 1px solid black;
background: rgba(0, 0, 0, 0.2);
padding: 8px 16px;
}
<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">
<h3>APP</h3>
<p>
<router-link to="/foo">Go to Foo</router-link><br />
<router-link to="/foo/1">Go to Foo-1</router-link><br />
<router-link to="/foo/2">Go to Foo-2</router-link><br />
<router-link to="/bar">Go to Bar</router-link><br />
<router-link to="/baz">Go to Baz</router-link><br />
</p>
<h3>ROUTES:</h3>
<router-view></router-view>
</div>
2. This is the /product parent + :id children
const Foo = {
template: `
<div>
Foo
<router-view></router-view>
</div>
`
}
const FooId = {
template: `
<div>Foo+{{ $route.params.id }}</div>
`
}
const Bar = {
template: `
<div>Bar</div>
`
}
const Baz = {
template: `
<div>Baz</div>
`
}
const routes = [{
path: '/foo',
component: Foo,
children: [{
path: ':id',
component: FooId
}]
},
{
path: '/bar',
component: Bar
},
{
path: '/baz',
component: Baz
}
]
const router = new VueRouter({
routes
})
new Vue({
router,
el: "#app",
})
div {
border: 1px solid black;
background: rgba(0, 0, 0, 0.2);
padding: 8px 16px;
}
<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">
<h3>APP</h3>
<p>
<router-link to="/foo">Go to Foo</router-link><br />
<router-link to="/foo/1">Go to Foo-1</router-link><br />
<router-link to="/foo/2">Go to Foo-2</router-link><br />
<router-link to="/bar">Go to Bar</router-link><br />
<router-link to="/baz">Go to Baz</router-link><br />
</p>
<h3>ROUTES:</h3>
<router-view></router-view>
</div>
3. Difference
The other name for children routes is nested routes. That means that a route is treated as root, and there's another router-view inside it (Ok, this is only for concept-explanation). (Nested routes)
So, the question is: do you want separate pages for products and each product (v1 - two separate routes), or you want a parent page for all your products and control the subsection of THAT page for each product (v2 - nested routes).
EDIT
Added a bit of CSS, so it's more understandable that what's inside what.

VueJS | How can i get url parameters in vue.js?

Hi I'm making my own websites. and i'm newbie vue.js
I'm trying to get parameters to url.
I've been trying to any method. but not works.
Here is a url. -> example.com:8080/login
in this page, there's a button to register.
All i want is when i give url parameter(example.com:8080/login?id=hello&pw=1234), in login.vue, insert value -> user_id = hello, user_pw = 1234 and going back to exapmle.com:/8080
i'm trying to using vue.router. but it not works.
the error is
javax.servlet.ServletException: Circular view path [error]: would dispatch back to the current handler URL [/error] again. Check your ViewResolver setup!
and this is /router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Main from '../views/Main.vue'
import Login from '../views/Login.vue'
import Intro from '../views/Intro.vue'
import Info from '../views/Info.vue'
import Setting from '../views/Setting.vue'
import store from '../store'
import user_id from '../views/Login.vue'
import user_pw from '../views/Login.vue'
Vue.use(VueRouter)
const routes = [{
path: '/',
redirect: '/main',
},
{
path: '/login',
name: 'login',
component: Login,
},
{
path: '/signup',
name: '/signup',
component: SignUp
},
{
path: '/main',
component: Main,
beforeEnter(to, from, next) {
if (store.state.accessToken) {
next();
} else {
next('/login');
}
},
children: [{
path: '',
name: 'intro',
component: Intro,
},
{
path: '/info',
name: 'info',
component: Info,
},
{
path: '/setting',
name: 'setting',
component: Setting,
},
]
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes: Login
});
var myApp = new Vue({
router,
el: '#app',
mounted: function() {
let parameters;
parameters = this.$route.query
console.log(parameters)
user_id = this.$route.query.id
user_pw = this.$route.query.pw
}
})
export default router
and this is part of login.vue
export default {
name: "test",
function() {
return {
id: "",
pw: "",
};
},
methods: {
test() {
axios.post("/login", {
id: this.userId,
pw: this.password
})
.then(function(response) {
if(response.data.code === 200) {
}
})
},
mounted : function() {
this.load();
}
}
i don't know what is wrong in my code.
my explain is too bad. sorry. but i'm trying to do my best
You are assigning routes to the Login component.
Replace
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes: Login
});
with
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
});
"Hello world" example (Maybe it will be helpful). Click on the link to get utm_source:
const User = {
template: `<div><b>User:</b> {{ this.$route.params.id }} | <b>utm_source:</b>
{{this.$router.currentRoute.query['utm_source']}}</div>`
}
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User }
]
})
const app = new Vue({ 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">
<nav>
<router-link to="/user/foo?utm_source=facebook">Click her to see the utm_source=facebook of /user/foo?utm_source=facebook</router-link>
</nav>
<router-view></router-view>
</div>

Loading Default Component - Vue.js CDN

How do I load a component in the <router-view> when the page by default on that page? I want to have a default when there is no :id
<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="/product">/product</router-link>
<router-link to="/product/foo">/product/foo</router-link>
</p>
<router-view>
</router-view>
</div>
<script>
const Product = {template: `<div class="user"> <h2>User {{ $route.params.id }}</h2></div> `}
const router = new VueRouter({
routes: [
{
path: '/product/:id', component: Product,
}
],
mode: 'history',
})
const app = new Vue({
router
})
.$mount('#app')
</script>
For the vue router you can use optional parameter.
So instead of path: '/product/:id' you can write path: '/product/:id? (added ? at the end)
<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="/product">/product</router-link>
<router-link to="/product/foo">/product/foo</router-link>
</p>
<router-view></router-view>
</div>
<script>
const Product = {
/*
router `id` will be passed as prop
so we can use `id` in our templates instead of $route.params.id
this way we can also specify the default value is nothing was passed
*/
template: `<div class="user"> <h2>User {{ id }}</h2></div> `,
props: {
id: {
type: String,
// specify default value if id is not passed to the router
default: 'N/A'
}
}
}
const router = new VueRouter({
mode: 'history',
routes: [
{
// :id? means that it's an optional parameter
path: '/product/:id?',
component: Product,
// Passing Props to Route Components
props: true
},
],
})
const app = new Vue({
router
})
.$mount('#app')
</script>

How to pass app data to a VueRouter component

I am using VueRouter to load templates depending on the URL. When I try to use a property defined in app.data in the components, I receive a [VueWarn] Property or method "role" is not defined.
How can I pass every data property to the child components?
This is my script:
const Home = { template: '<p>home page, {{role}}</p>' }
const NotFound = { template: '<p>Page not found</p>' }
const routes = [
{path: '/', component: Home}
{path: '*', component: NotFound}
]
Vue.use(VueRouter)
var app = new Vue({
el: '#app',
data: {
role: 0,
cookiesAlert: true
},
router: new VueRouter({routes})
})
I think your router construction options are not set properly. Usually, I prefer to use 'named routes', therefore what I will set is:
const router = new VueRouter({
routes: [
{ name: 'role', path: '/:role', component: User },
{ path: '*', component: Home }
]
})
And if I don't understand your question wrong, what you want to do is pass the 'data' in parent components to child components via url and read the data in child component?
const User = {
template: '<div><br/>Role read from url is {{ $route.params.role }}</div>'
}
const Home = {
template: '<div><br/>Welcome</div>'
}
const router = new VueRouter({
routes: [
{ name: 'role', path: '/:role', component: User },
{ path: '*', component: Home }
]
})
new Vue({
router,
el: '#app',
data: {
role: 'default role'
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.2/vue-router.min.js"></script>
<div id="app">
The role is (Please change the 'role' value and click on '/User' link): <input v-model="role" type="text" /> <br/>
<router-link :to="{ name: 'role', params: { role: role }}">User</router-link>
<router-link to="/">Home</router-link>
<router-view></router-view>
</div>
Or if you don't want to use $route.params.role, what I will do is to set the 'props' in router config options to be true.
When props is set to true, the route.params will be set as the component props.
const router = new VueRouter({
routes: [
{ name: 'role', path: '/:role', component: User, props: true },
{ path: '*', component: Home }
]
})
And bind to the 'props' inside child components.
const User = {
props: ['role'],
template: '<div><br/>Role read from url is {{ role }}</div>'
}

Vue children Router: url changed but display parent component

I am learning Vue and stuck with nested router, I define some children router in the routes,but when I visit the child route it still display the parent component, my code is as following:
App.vue:
<template>
<div id="app">
<img src="./assets/logo.png">
<router-link :to="{name: 'Home'}">Home</router-link>
<router-link to="/cart">Cart</router-link>
<router-link to="/admin">Admin</router-link>
<router-link to="/admin/add">【Admin Add】</router-link>
<router-link to="/admin/edit">Admin Edit</router-link>
<router-view/>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Router/index.js:
import Vue from 'vue'
import Router from 'vue-router'
import Home from '#/components/pages/Home'
import Cart from '#/components/pages/Cart'
import Index from '#/components/pages/Admin/Index'
import Add from '#/components/pages/Admin/Add'
import Edit from '#/components/pages/Edit'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/cart',
name: 'Cart',
component: Cart
},
// {
// path: '/admin/index',
// name: 'Index',
// component: Index
// },
// {
// path: '/admin/add',
// name: 'Add',
// component: Add
// },
// {
// path: '/admin/edit',
// name: 'Edit',
// component: Edit
// }
{
path: '/admin',
// name: 'Admin',
component: Index,
children: [
{
path: 'add',
name: 'Add',
component: Add
},
{
path: 'edit',
name: 'Edit',
component: Edit
}
]
}
]
})
I tried not to use the children router, it will display the component correctly, just as the code which is commented.
I am so confused with this, please help me.
In your Index component you will need to add <router-view></router-view>. Check out this working example from the vue-router docs.
const User = {
template: `
<div class="user">
<h2>User {{ $route.params.id }}</h2>
<router-view></router-view>
</div>
`
}
const UserHome = { template: '<div>Home</div>' }
const UserProfile = { template: '<div>Profile</div>' }
const UserPosts = { template: '<div>Posts</div>' }
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User,
children: [
// UserHome will be rendered inside User's <router-view>
// when /user/:id is matched
{ path: '', component: UserHome },
// UserProfile will be rendered inside User's <router-view>
// when /user/:id/profile is matched
{ path: 'profile', component: UserProfile },
// UserPosts will be rendered inside User's <router-view>
// when /user/:id/posts is matched
{ path: 'posts', component: UserPosts }
]
}
]
})
const app = new Vue({ 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">
<p>
<router-link to="/user/foo">/user/foo</router-link>
<router-link to="/user/foo/profile">/user/foo/profile</router-link>
<router-link to="/user/foo/posts">/user/foo/posts</router-link>
</p>
<router-view></router-view>
</div>

Categories

Resources