Loading Default Component - Vue.js CDN - javascript

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>

Related

Assign refs to child components using VueRouter - Vue

I have the following code in my main.js file in my Vue webapp:
const routes = {
name: "Main",
path: "/main",
redirect: "/main/home",
component: MainComponent,
children: [
{ path: "home", name: "Main_Home", component: MainHomeComponent },
{ path: "play", name: "Main_Play", component: PlayComponent },
]
}
Vue.config.productionTip = false;
const router = new VueRouter({
mode: 'history',
routes
});
Currently, the routing and component rendering is working really well, however from my MainComponent, I want to trigger a method within a child component. I understand that I can do that with refs in Vue, however I'm not sure how I can create them with VueRouter, as the components are being loaded by VueRouter. Here is my MainComponent.js:
<template>
<div id="main">
<h1>Main Component</h1>
<router-view></router-view>
</div>
</template>
A template ref on the router-view will automatically apply to the view's rendered component. With that template ref, you could access the child's method directly:
<template>
<div id="main">
<h1>Main Component</h1>
<button #click="callChildMethod">Call child method</button>
<router-view ref="view"></router-view>
</div>
</template>
<script>
export default {
methods: {
callChildMethod() {
this.$refs.view.myMethod()
}
}
}
</script>
demo

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.

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.js nested routing

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>

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