How to call function from router template? - vue.js

I am doing very simple page with url's switching. In one of url I need to call #click methods. Here is my code:
const NotFound = { template: '<p>Page not found</p>' }
const Home = { template: '<p>home page</p>' }
const Faq = { template: '<p>Faq page</p>' }
const Book = { template: `
<div>
<button #click="foo()">test</button>
</div>
` }
const routes = [
{path: '/', component: Home},
{path: '/book', component: Book},
{path: '/faq', component: Faq}
]
const router = new VueRouter({
routes // short for `routes: routes`
})
new Vue({
el: '#app',
router,
data: {
},
methods:
{
foo()
{
console.log("ffffff");
}
}
})
But I am getting error: Property or method "foo" is not defined on the instance but referenced during render.

Because you're trying to define child component(book)'s method in parent component. Please just move methods property from parent component to child component.
Here's a sample.
const NotFound = { template: '<p>Page not found</p>' }
const Home = { template: '<p>home page</p>' }
const Faq = { template: '<p>Faq page</p>' }
const Book = { template: `
<div>
<button #click="foo()">test</button>
</div>
`
, methods: // <-- here you go
{
foo()
{
console.log("ffffff");
}
}}
const routes = [
{path: '/', component: Home},
{path: '/book', component: Book},
{path: '/faq', component: Faq}
]
const router = new VueRouter({
routes // short for `routes: routes`
})
Vue.use(VueRouter);
new Vue({
el: '#app',
router,
data: {
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/2.7.0/vue-router.min.js"></script>
<div id="app">
<router-link :to="{ path: '/' }">Home</router-link>
<router-link :to="{ path: '/faq' }">FAQ</router-link>
<router-link :to="{ path: '/book' }">book</router-link>
<router-view></router-view>
</div>

Related

How to open this route in new window?

if (success) {
context.bookingData.city = context.city;
context.bookingData.departureFlightDate = context.departureFlightDate;
context.bookingData.arrivalFlightDate = context.arrivalFlightDate;
context.bookingData.idParkingService = context.idParkingService;
context.bookingData.Price = context.bookings.price.items.data.price;
//const booking = JSON.stringify(context.bookingData);
context.addBookingData(context.bookingData);
context.$router.push({
path: "parkplatz-buchen-schritt-2",
});
}
how to open this path in new window or tab at the same time I have to pass context data to the destination
To open the route in a new window
Home.vue
<template>
<button v-on:click="openInNewWindow()">Open in new window</button>
</template>
<script>
export default {
methods: {
openInNewWindow(){
let routeData = this.$router.resolve({
path: '/about',
query: {
city : 'test',
departureFlightDate : 'test',
arrivalFlightDate : 'test',
idParkingService : 'test',
price : 'test'
}
});
window.open(routeData.href, '_blank');
}
}
}
</script>
Router
import Home from '../views/Home.vue'
import About from '../views/About.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router
About.vue
<template>
<div class="about">
<h1>This is an about page</h1>
{{this.$route.query.city}}
</div>
</template>
<script>
export default {
mounted(){
console.log(this.$route.query)
}
}
</script>

Vue - Keep default Router-View alive when change another named view

Situation:
I use, beside of the default route-view, a named route-view. I want to keep the DEFAULT route-view alive when I call the ArticleComponent, but as you can see, you can call the ArticleComponent from 2 different routes/components. You can find a fiddle link under the code snippet.
What I want to do:
If I open the ArticleComponent from ListingComponent, then ListingComponent should stay alive in the default route-view.
If I call the ArticleComponent from the FeedComponent, then the FeedComponent should stay alive in the default route-view.
My code:
const HomeComponent = {
template: '<h4>Home</h4>'
};
const FeedComponent = {
template: `<div>
<h4>FeedComponent</h4>
<router-link to="/article/1">Article 1</router-link> -
<router-link to="/article/2">Article 2</router-link>
</div>`
};
const ListingComponent = {
template: `<div>
<h4>ListingComponent</h4>
<router-link to="/article/1">Article 1</router-link> -
<router-link to="/article/2">Article 2</router-link> -
<router-link to="/article/3">Article 3</router-link>
</div>`
};
const ArticleComponent = {
template: `<h4>Article {{ $route.params.id }}</h4>`
};
const routes = [
{
path: '/',
component: HomeComponent
},
{
path: '/feed',
component: FeedComponent
},
{
path: '/listing',
component: ListingComponent
},
{
path: '/article/:id?',
components: {
default: FeedComponent, // <--- dynamically
secondary: ArticleComponent
}
}
];
const router = new VueRouter({
routes
});
new Vue({
el: '#app',
router
});
Fiddle:
https://jsfiddle.net/kvnvooo/b589uvLt/9/
You can use Navigation guards to alter default component dynamically...
{
path: '/article/:id?',
components: {
default: FeedComponent,
secondary: ArticleComponent
},
beforeEnter: (to, from, next) => {
if(from.fullPath === '/listing') {
to.matched[0].components.default = ListingComponent
} else if(from.fullPath === '/feed') {
to.matched[0].components.default = FeedComponent
}
next();
}
}
https://jsfiddle.net/dhmLby6f/7/

Vue lifecycle events triggers on every route

According to the documentation https://v2.vuejs.org/v2/guide/instance.html#Lifecycle-Diagram all events from beforeCreate till mounted should be called once. But they are being triggered on every vue-router path navigated
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App },
created: function () {
this.$http.get('/user/get').then(response => {
if (response.data.error) {
console.log(response.data.error)
} else {
User.set(response.data.user)
router.go('/dashboard') // this does force looping
}
}, response => {
router.go('/')
})
}
})
This is App.vue
<template>
<div id="app">
<topmenu></topmenu>
<router-view></router-view>
</div>
</template>
<script>
import Topmenu from '#/components/topmenu'
export default {
name: 'app',
components: {
topmenu: Topmenu
}
}
</script>
The Router.vue
Vue.use(Router)
let route = new Router({
routes: [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/user/signup',
name: 'Signup',
component: Signup
},
{
path: '/dashboard',
name: 'Dashboard',
component: Dashboard
}
]
})
route.beforeEach((to, from, next) => {
if (to.path.match(/^(\/|\/signup)$/)) {
return next()
}
if (User.valid()) {
return next()
}
route.push('/')
})
export default route
How to avoid this events from being triggered on every route switched?

Why Vue Router doesn't run javascript transition hooks sync?

I am new in vue router and vue.js. I just try to use javascript transitions on vue-router. Why beforeLeave event doesn't fire before route change ? But it is working as expected with css transitions. it works great with css transitions. But it doesn't work with javascript transitions... Here is jsfiddle example...enter method works as expected. but beforeLeave method doesn't work as expected and has no transition chain between routes. Please help..
jsfiddle
<script src="https://npmcdn.com/vue/dist/vue.js"></script>
<script src="https://npmcdn.com/vue-router/dist/vue-router.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.1/TweenMax.min.js"></script>
<div id="app">
<router-link to="/">/home</router-link>
<router-link to="/foo">/foo</router-link>
<router-view></router-view>
</div>
and this is js
const Home = { template: '<transition v-on:enter="enter" v-on:leave="leave" ><div>Home</div></transition>',
methods:{
enter:function(el, done){
TweenMax.from(el,2,{x:-60,onComplete:done});
},
leave:function(el, done){
TweenMax.to(el,2,{x:60,onComplete:done});
}
}
}
const Foo = { template: '<transition v-on:enter="enter" v-on:leave="leave" ><div>Foo</div></transition>',
methods:{
enter:function(el, done){
TweenMax.from(el,2,{x:-60,onComplete:done});
},
leave:function(el, done){
TweenMax.to(el,2,{x:60,onComplete:done});
}
}
}
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '/', component: Home },
{ path: '/foo', component: Foo }
]
})
new Vue({
router,
el: '#app',
data: {
msg: 'Hello World'
}
})
I have solved it. Do not use multiple transitions for chaining. if you use css transition it is not problem. But if you use javascript transition it will not run as expected. So use transition on parent element which is "router-view". if you want to change transition for each route, just check route.name with an if block and make a transition for specific route.
here is jsfiddle
const Home = { template: '<div>Home</div>',
methods:{
enter:function(el, done){
TweenMax.from(el,2,{x:-60,onComplete:done});
},
leave:function(el, done){
TweenMax.to(el,2,{x:60,onComplete:done});
}
}
}
const Foo = { template: '<div>Foo</div>',
methods:{
enter:function(el, done){
TweenMax.from(el,2,{x:-60,onComplete:done});
},
leave:function(el, done){
TweenMax.to(el,2,{x:60,onComplete:done});
}
}
}
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '/', component: Home },
{ path: '/foo', component: Foo }
]
})
new Vue({
router,
el: '#app',
data: {
msg: 'Hello World'
},
methods:{
enter:function(el, done){
TweenMax.from(el,2,{x:-60,onComplete:done});
},
leave:function(el, done){
TweenMax.to(el,2,{x:60,onComplete:done});
}
}
})

Vue Component Issue

I have this page I want to try out Vue Router with Vue Components. I cant figure out whats wrong. I am getting an error Uncaught TypeError: Cannot read property 'name' of undefined at this line const App = new Vue.extend({})
<body>
<div id="app">
<router-view></router-view>
</div>
<template id="foo"> <h1>This is homepage</h1> </template>
<template id="bar"> <h1>This is Bar page</h1> </template>
</body>
//Vue.js v1.0.28
<script src="{{ asset( 'js/vue.js' ) }}"></script>
// vue-router v0.7.13
<script src="{{ asset( 'js/vue-router.js' ) }}"></script>
<script>
const router = new VueRouter()
const App = new Vue.extend({})
router.map({
'/': {
component: {
template: '#foo'
}
},
'/bar': {
component: {
template: '#bar'
}
},
})
router.start(App, '#app')
</script>
</html>
What am I doing wrong?
EDIT:
Okay, I have managed to get this working.
const Foo = Vue.component('foo', { template: '#foo' });
const Bar = Vue.component('bar', { template: '#bar' });
Vue.use(VueRouter)
const router = new VueRouter()
router.map({
'/foo': {
component: Foo
},
'/bar': {
component: Bar
},
})
var App = Vue.extend({})
router.start(App, 'body')
What I need now is to extract those templates from index.blade.php into their own files like Foo.vue and Bar.vue. How do I do that?
I am using Webpack to compile assets.
You could try to use vue-router v.v2.2.1 and you can check this official example https://github.com/vuejs/vue-hackernews-2.0 and here router code:
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
import { createListView } from '../views/CreateListView'
import ItemView from '../views/ItemView.vue'
import UserView from '../views/UserView.vue'
export default new Router({
mode: 'history',
scrollBehavior: () => ({ y: 0 }),
routes: [
{ path: '/top/:page(\\d+)?', component: createListView('top') },
{ path: '/new/:page(\\d+)?', component: createListView('new') },
{ path: '/show/:page(\\d+)?', component: createListView('show') },
{ path: '/ask/:page(\\d+)?', component: createListView('ask') },
{ path: '/job/:page(\\d+)?', component: createListView('job') },
{ path: '/item/:id(\\d+)', component: ItemView },
{ path: '/user/:id', component: UserView },
{ path: '/', redirect: '/top' }
]
})