Vue router and Bootstrap - vue.js

I'm using Vue with vue-router and vue-strap. I'm trying to register components from vue-strap, but the examples look like this:
var alert = require('vue-strap').alert;
new Vue({
components: {
alert: alert
}
})
vue-router, on the other hand, doesn't create a Vue object.
Vue.use(VueRouter);
const router = new VueRouter({
history: true,
linkActiveClass : 'active'
});
router.map({
'/': {
component: Home
}
});
const App = Vue.extend(Index);
router.start(App, '#root');
So how do I declare my components?

This is my current setup in vue apps
var Vue = require('vue');
var VueRouter = require('vue-router');
// Use
Vue.use(require('vue-resource'));
Vue.use(VueRouter);
// Components
var site = Vue.component('site', require('./views/site/component.vue'));
var home = Vue.component('home', require('./views/home/component.vue'));
var search = Vue.component('search', require('./views/search/component.vue'));
var index = Vue.component('index', require('./views/index/component.vue'));
// Router
var router = new VueRouter({
history: true
});
router.map({
'/': {
component: index
},
'/search': {
component: search
},
'/profile': {
component: home
}
})
// Start App
router.start(site, 'body');
All 'major' components are declared globally with .component. Everything that I need at component level I declare with .extend. In vue-router, the 'site' component (in my case) acts as the $root.
Topmenu / sidebar are declared in the site component in the components section.
In the 'site' template i have only and other shared components like topmenu / sidebar.

you can try it instead,
import { alert } from 'vue-strap'
Vue.use(VueRouter);
const router = new VueRouter({
history: true,
linkActiveClass : 'active'
});
router.map({
'/': {
component: alert
}
});
const App = Vue.extend(Index);
router.start(App, '#root');

Related

Cannot get vue-router to work

Got this working with a single page. It's when I introduce vue-router that nothing will render.
In main.js, if I return app.js with sample text and few edits; it renders fine with no issues. Seems it has to do with how I'm instantiating vue-router. Also, no console errors in my environment.
main.js
define(function(require) {
'use strict';
var Vue = require('vue');
var VueRouter = require('vue-router');
var App = require('app');
var Foo = { template: '<div>oijsdfoijsdoifjdsf</div>' }
var Bar = { template: '<div>bar</div>' }
Vue.use(VueRouter);
var routes = [
{ path: '/aaa', component: Foo },
{ path: '/bbb', component: Bar }
]
var router = new VueRouter({
routes: routes
});
return new Vue({
el: '#vue',
router: router,
render: function(h) {
h(App);
}
});
});
app.js
define(function(require) {
'use strict';
var Vue = require('vue');
return new Vue({
template: '<div id="vue"><router-view></router-view></div>'
});
});
From my experience, you can change your router configuration to:
const router = new VueRouter({
base: __dirname, // or '/'
routes: routes
})
You haven't defined a root route, e.g. /. So you wouldn't see any component render at /. Can you navigate to /aaa and see something? Also, shouldn't those route components be passed to Vue.component?

Why isn't router.currentRoute.path reactive?

I have an app which is contained in this div:
<div id="app" v-bind:style='{backgroundColor: backgroundColor}'>
... the app ...
</div>
The routing is done following the example in the documentation (this is a webpack project):
import Vue from 'vue/dist/vue.js'
import VueRouter from 'vue-router'
import ComponentOne from './component1.vue'
import ComponentTwo from './component2.vue'
Vue.use(VueRouter)
const routes = [{
path: '/foo',
component: ComponentOne
},
{
path: '/bar',
component: ComponentTwo
}
]
const router = new VueRouter({
routes // short for `routes: routes`
})
const app = new Vue({
router,
data: {
day: "Monday"
},
computed: {
backgroundColor: function () {
console.log(JSON.stringify(router.currentRoute))
if (router.currentRoute.path == "/foo") {
return "green"
} else {
return "blue"
}
}
}
}).$mount('#app')
I wanted the background to be dependent on the current route (router.currentRoute.path).
But, the solution above does not work, because router.currentRoute.path is not detected by the Vue instance as having changed (is not reactive).
What is the correct way to access the dynamic router data from within the Vue instance?
The router object created via new VueRouter is not reactive because Vue has no way to know to watch and update any object outside of its scope.
Passing router in the Vue config object is what allows the current route to be watched, but you need to reference it via this.$route:
if (this.$route.path == "/foo") {
...
}
You can also access the entire router object via this.$router, but its data is not reactive.
And if you are using Vue 2 with composition api setup() approach you can do this:
import { computed } from '#vue/composition-api'
export default {
setup (props, context) {
const params = computed ( () => context.root.$route.params)
const path = computed( () => context.root.$route.path)
I found on Vue's documentation page that tracks the router using watch for transition animations. Not sure if this is a best practice but you can use to.path or from.path to grab the path instead.
// then, in the parent component,
// watch the `$route` to determine the transition to use
watch: {
'$route': (to, from) => {
const toDepth = to.path.split('/').length
const fromDepth = from.path.split('/').length
this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
}
}

Vue Router: Keep query parameter and use same view for children

I'm rewriting an existing Angular 1 application with Vue.
The application always needs to authenticate an user by locale, id and token before entering any views. Respecting the conventions of our API, I specified the token as a query parameter within my main parent route.
Coming from the existing Angular's UI router implementation I thought this is the way to go:
// main.js
new Vue({
el: '#app',
router,
store,
template: '<router-view name="main"></router-view>'
})
// router.js
const router = new Router({
mode: 'history',
routes: [
{
name: 'start',
path : '/:locale/:id', // /:locale/:id?token didn't work
query: {
token: null
},
beforeEnter (to, from, next) {
// 1. Get data from API via locale, id and token
// 2. Update store with user data
},
components: {
main: startComponent
},
children: [{
name: 'profile',
path: 'profile',
components: {
main: profileComponent
}
}]
}
]
})
When I navigate to the profile view, I expect the view to change and the query token to stay, e.g. /en-US/123?token=abc to /en-US/123/profile?token=abc. Neither happens.
I'm using Vue 2.3.3 and Vue Router 2.3.1.
Questions:
Can I keep query parameters when navigating to child routes?
Am I using the Vue router right here? Or do I need to blame my UI router bias?
You can resolve this in the global hooks of Router
import VueRouter from 'vue-router';
import routes from './routes';
const Router = new VueRouter({
mode: 'history',
routes
});
function hasQueryParams(route) {
return !!Object.keys(route.query).length
}
Router.beforeEach((to, from, next) => {
if(!hasQueryParams(to) && hasQueryParams(from)){
next({name: to.name, query: from.query});
} else {
next()
}
})
If the new route (to) does not have its own parameters, then they will be taken from the previous route (from)
You can add in a mounted hook a router navigation guard beforeEach like this preserveQueryParams:
// helpers.js
import isEmpty from 'lodash/isEmpty';
const preserveQueryParams = (to, from, next) => {
const usePreviousQueryParams = isEmpty(to.query) && !isEmpty(from.query);
if (usePreviousQueryParams) {
next({ ...to, query: from.query });
} else {
next();
}
};
// StartComponent.vue
removeBeforeEachRouteGuard: Function;
mounted() {
this.removeBeforeEachRouteGuard = this.$router.beforeEach(preserveQueryParams);
}
// don't forget to remove created guard
destroyed() {
this.removeBeforeEachRouteGuard();
// resetting query can be useful too
this.$router.push({ query: undefined });
}

Vue Router this.$route.router undefined

I'm trying to redirect the url using router.push({ path: 'customers', query : mergedQuery }); but I can't get a correct reference to router property.
I feel like I'm missing something in the app.js but not sure which one. Inside component this.$route has some stuff inside it but there's no router property.
app.js
window.Vue = require('vue');
window.VueRouter = require('vue-router');
window.VueResource = require('vue-resource');
window.Vue.use(window.VueRouter);
const routes = [
{ path: '/', component: require('./components/dashboard.vue') },
{ path: '/customers/', component: require('./components/customers/list.vue') },
];
const router = new VueRouter({routes});
const app = new Vue({router}).$mount('#app');
.vue file
console.log(this.$route.router); //undefined
You're accessing it incorrectly. According to the official docs, router is available inside component instances as this.$router.

Vue Router router-view error

I'm getting the following error when trying to implement vue-router.
Unknown custom element: <router-view> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
Where do I need to provide the name option?
A lot of the tutorials I'm looking at seem to be an older version of vue-router. I follow the set-up process but can't get it to work.
Might there be something special I have to do when using the webpack cli template?
I'm also using the vue-router cdn.
Here's my main.js
import Vue from 'vue'
import App from './App'
import ResourceInfo from '../src/components/ResourceInfo'
var db = firebase.database();
var auth = firebase.auth();
const routes = [
{ path: '/', component: App },
{ path: '/info', component: ResourceInfo }
]
const router = new VueRouter({
routes
})
/* eslint-disable no-new */
var vm = new Vue({
el: '#app',
components: { App },
created: function() {
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// Get info for currently signed in user.
console.log(user);
vm.currentUser = user;
console.log(vm.currentUser);
} else {
// No user is signed in.
}
})
// Import firebase data
var quizzesRef = db.ref('quizzes');
quizzesRef.on('value', function(snapshot) {
vm.quizzes = snapshot.val();
console.log(vm.quizzes);
})
var resourcesRef = db.ref('resources');
resourcesRef.on('value', function(snapshot) {
vm.resources.push(snapshot.val());
console.log(vm.resources);
})
var usersRef = db.ref('users');
usersRef.on('value', function(snapshot) {
vm.users = snapshot.val();
console.log(vm.users);
})
},
firebase: {
quizzes: {
source: db.ref('quizzes'),
asObject: true
},
users: {
source: db.ref('users'),
asObject: true
},
resources: db.ref('resources')
},
data: function() {
return {
users: {},
currentUser: {},
quizzes: {},
resources: []
}
},
router,
render: h => h(App)
})
And my App.vue
<template>
<div id="app">
<navbar></navbar>
<resource-info :current-user="currentUser"></resource-info>
<router-view></router-view>
</div>
</template>
<script>
import Navbar from './components/Navbar'
import ResourceInfo from './components/ResourceInfo'
export default {
name: 'app',
props: ['current-user'],
components: {
Navbar,
ResourceInfo
}
}
</script>
<style>
</style>
In your main.js file, you need to import VueRouter as follows:
import Vue from "vue" // you are doing this already
import VueRouter from "vue-router" // this needs to be done
And below that, you need to initialize the router module as follows:
// Initialize router module
Vue.use(VueRouter)
Other than the above, I cannot find anything else missing in your code, it seems fine to me.
Please refer to the installation page in docs, under NPM section:
http://router.vuejs.org/en/installation.html
First install vue router by using "npm install vue-route" and follow the bellow in main.js
import Vue from 'vue'
import Router from 'vue-router'
import App from './App'
import ResourceInfo from '../src/components/ResourceInfo'
var db = firebase.database();
var auth = firebase.auth();
Vue.use(Router)
var router = new Router({
hashbang: false,
history: true,
linkActiveClass: 'active',
mode: 'html5'
})
router.map({
'/': {
name: 'app',
component: App
},
'/info': {
name: 'resourceInfo',
component: ResourceInfo
}
})
// If no route is matched redirect home
router.redirect({
'*': '/'
});
// Start up our app
router.start(App, '#app')
This might be solve your problem
You forgot to import vue-router and initialize VueRouter in main.js
import VueRouter from "vue-router"
Vue.use(VueRouter)