I'm trying to set the class nav-active to the correct nav element, based from what url you're directly accessing the webapp for the first time.
I have a few routes:
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'home',
component: () => import('./views/Home.vue')
},
{
path: '/account',
name: 'account',
component: () => import('./views/Account.vue')
}
]
});
And this is my navigation bar component (NavBar):
export default {
name: 'NavBar',
components: {
NavLogo,
NavItem
},
data() {
return {
navItems: [
{ /* root navigation */
id: 0,
type: 'root',
name: 'home',
route: '/',
active: this.$route.name === 'home' },
{
id: 1,
type: 'root',
name: 'account',
route: '/account',
active: false
}
}
}
}
The state of the active boolean inside navItems determines whether the navigation element should have the nav-active class. I'm trying to use the current route to determine whether active should be true or false, by using it this way:
active: this.$route.name === 'account'
But once for example I enter this dashboard directly from: http://localhost:8000/account
this.$route's items are all empty and the path is always /
Help is much appreciated,
Thanks
You are not tracking this.$route.name changes by default with this approach.
Try creating a computed property that resolves to this.$route.name, and use this in your data property declaration. In fact, you can just stick the whole thing in a computed property, since you're unlikely to change this.
export default {
name: 'NavBar',
components: {
NavLogo,
NavItem
},
computed: {
routeName(){
return this.$route.name
},
navItems(){
return [
{ /* root navigation */
id: 0,
type: 'root',
name: 'home',
route: '/',
active: this.routeName === 'home' },
{
id: 1,
type: 'root',
name: 'account',
route: '/account',
active: false
}
]
}
}
}
Related
I need to load a route outside the app.vue, I have a dashboard that works fine then I decided to implement a login which implied changing the app.vue, so after changing it I have the problem that my dashboard loads inside app.vue thus taking the styles of app.vue and completely deforming, so what now I need is to load outside of app.vue so it can work properly like it did before.
These are my routes:
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
mode: 'history', // to disappear the # in URL's
base: process.env.BASE_URL,
routes: [
//HOME
{
name: 'Home',
path: '/',
component: () => import('#/components/Home.vue'),
},
//LOGIN
{
name: 'Login',
path: '/login',
//component: () => import('#/views/login/Login'),
component: () => import('#/components/Login.vue'),
},
//REGISTER
{
name: 'Register',
path: '/register',
component: () => import('#/components/Register.vue'),
},
//DASHBOARD
{
//name: 'Dashboard',
path: '/dash',
name: 'dashboardd',
component: () => import('#/views/dashboard/Index'),
children: [
//CLIENTS
{
name: 'Clients',
path: '/Clients',
component:()=> import('#/views/clientss/Clientss')
},
//SALES
{
name: 'Sales',
path: '/sales',
component:()=> import('#/views/sales/Sales')
},
//NUEVA VENTA
{
name: 'Sales',
path: '/new-sale',
component:()=> import('#/views/sales/NewSale')
},
//productos
{
name: 'Productos',
path: '/products',
component:()=> import('#/views/articulos/Products')
},
//listar articulos
{
name: 'ListarArticulos',
path: '/articulos',
component:()=> import('#/views/articulos/ListarArticulos')
},
//crear articulo
{
name: 'CrearArticulo',
path: '/articulos/crear',
component:()=> import('#/views/articulos/CrearArticulo')
},
//editar articulo
{
name: 'EditarArticulo',
path: '/articulos/editar/:id',
component:()=> import('#/views/articulos/EditarArticulo')
},
// Dashboard
{
name: 'Dashboard',
path: '/dash',
component: () => import('#/views/dashboard/Dashboard'),
},
{
name: 'PROVEEDORES',
path: '/providers',
component: () => import('#/views/providers/Provider'),
},
{
name: 'USUARIOS',
path: '/users',
component: () => import('#/views/users/User'),
},
{
name: 'REPORTES',
path: '/reports',
component: () => import('#/views/reports/Report'),
},
// Pages
{
name: 'User Profile',
path: 'pages/user',
component: () => import('#/views/dashboard/pages/UserProfile'),
},
{
name: 'Notifications',
path: 'components/notifications',
component: () => import('#/views/dashboard/component/Notifications'),
},
{
name: 'Icons',
path: 'components/icons',
component: () => import('#/views/dashboard/component/Icons'),
},
// Maps
{
name: 'Google Maps',
path: 'maps/google-maps',
component: () => import('#/views/dashboard/maps/GoogleMaps'),
},
],
},
],
})
And I need to load the route named 'Dashboard' outside the App.vue. Because of my dashboard has his own styles and work properly when it is the only app running :
You can simply access the router from all components that are part of your Vue by using this.$router.
In Vue 2, you would need to call this.$router.push({name:'Dashboard'}) to instantly navigate to the route named 'Dashboard'.
I feel like I'm missing something very obvious but I can't figure it out. Please help!
I have the following routes defined:
const routes = [
{
path: '/',
name: 'Login',
component: () => import('../views/Login.vue'),
meta: {
authRedirect: true
}
},
{
path: '/companies',
name: 'Companies',
component: () => import('../views/Companies.vue'),
meta: {
requiresAuth: true
}
},
{
path: '/companies/:id',
name: 'Company',
component: () => import('../views/Company.vue'),
meta: {
requiresAuth: true
}
},
{
path: '*',
name: '404',
component: () => import('../views/404.vue')
}
]
Then I have the following in my component:
export default {
name: 'Company',
data() {
return {
company: {}
}
},
methods: {
getCompanyDetails: function() {
let self = this
axios.get('/api/companies/' + this.$route.params.id).then(function(response) {
self.company = response.data
}).catch(function() {
self.$router.push('companies')
})
}
},
created() {
this.getCompanyDetails()
}
}
Essentially everything is working if the API returns data, but inside the catch function I'm trying to push the route back to /companies. But it's redirecting to /companies/companies. How do I redirect it to the correct route?
Did you tried $router.push('/companies') (with a / in the path) ?
Also, you can use $router.push({ name: 'Companies' }) if you want to make it more clear, it will match the name defined in your routes.
My application have navbar with back button. The navbarTop is a named views, so I can have different navbar for each route, and the navbar needs props backRoute.
I define the back route like this:
{
path: '/:id',
name: 'orders detail',
components: {
default: OrderDetail,
navbarTop: Navbar,
},
props: {
navbarTop: {
backRoute: { name: 'orders' },
title: 'Order Detail',
},
default: true,
},
},
{
path: '/:id/request-cancel',
name: 'orders request cancel',
components: {
default: OrderRequestCancel,
navbarTop: Navbar,
},
props: {
navbarTop: {
backRoute: { name: 'orders', params: {id: ???} }, // how to get the id here?
title: 'Request Cancel',
},
default: true,
},
},
Is it possible to get the id in route and pass it as prop to the component?
The NavbarTop is named view and is used in many routes, so I can't update the back route from OrderRequestCancel component.
We can use Function Mode
props: {
navbarTop: route => ({
backRoute: { name: 'order detail', params: { id: route.params.id } },
title: 'Request Cancel',
}),
default: true,
},
Thank you #Yom S. for the hint.
I'm trying to handle route middleware of the children route, but I got this error
Uncaught TypeError: route.children.some is not a function
The documentation are only shows the example for a single route but in this case, I have a children route that needs to be restricted.
Please take a look at my router configuration:
import Vue from 'vue'
import Router from 'vue-router'
import store from './store/index'
import Home from './views/home/Index.vue'
Vue.use(Router)
let router = new Router({
mode: 'history',
base: process.env.VUE_APP_BASE_URL,
linkActiveClass: 'is-active',
linkExactActiveClass: 'is-exact-active',
routes: [{
path: '/',
name: 'home',
component: Home,
meta: {
requiresAuth: true
}
},
{
path: '/login',
name: 'login',
// route level code-splitting
// this generates a separate chunk (login.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import('./views/auth/Login.vue'),
meta: {
requiresGuest: true
}
},
{
path: '/register',
name: 'register',
component: () => import('./views/auth/Register.vue'),
meta: {
requiresGuest: true
}
},
{
path: '/forgot-password',
name: 'forgot-password',
component: () => import('./views/auth/extras/ForgotPassword.vue'),
meta: {
requiresGuest: true
}
},
{
path: '/database',
name: 'database',
component: () => import('./views/database/Index.vue'),
meta: {
requiresAuth: true
}
},
{
path: '/third-parties',
name: 'third-parties',
component: () => import('./views/third-parties/Index.vue'),
meta: {
requiresAuth: true
}
},
{
path: '/editor',
name: 'editor',
meta: {
requiresAuth: true,
requiresAdmin: true,
requiresEditor: true,
},
children: {
path: ':appSlug/layout-editor/:pageSlug',
name: 'layout-editor',
component: () => import('./views/editor/Index.vue'),
}
},
]
})
router.beforeEach((to, from, next) => {
const isLoggedIn = store.getters['auth/isLoggedIn'];
// Role getters
const isAdmin = (store.getters['auth/isAdmin'] == 'admin') || (store.getters['auth/isAdmin'] == 'super-admin');
const isEditor = store.getters['auth/isEditor'] == 'editor';
// Redirect to the login page if the user is not logged in
// and the route meta record is requires auth
if (to.matched.some(record => record.meta.requiresAuth) && !isLoggedIn) {
next('/login')
}
// Redirect to the homepage page if the user is logged in
// and the route meta record is requires guest
if (to.matched.some(record => record.meta.requiresGuest) && isLoggedIn) {
next('/')
}
// Redirect to the preview page if the user is logged in
// but has no role assigned or the role is user
if (to.matched.some(record => (
record.meta.requiresAuth &&
record.meta.requiresAdmin &&
record.meta.requiresEditor)) && !isAdmin && !isEditor) {
next('/preview')
}
// Pass any access if not match two conditions above
next()
})
export default router
Could somebody please explain it? Why I getting this error and how to fix it?
Thanks in advance.
I just found the answer, kinda silly tho.. I forgot to put square brackets on the children props. Now it's working as I expected.
fix:
{
path: '/editor',
name: 'editor',
meta: {
requiresAuth: true,
requiresAdmin: true,
requiresEditor: true,
},
children: [{
path: ':appSlug/layout-editor/:pageSlug',
name: 'layout-editor',
component: () => import('./views/editor/Index.vue'),
}]
},
Whether I do this
Vue.router.push({ path: '/beats/catalog/1' })
or this
Vue.router.push({ name: 'BeatsCatalog', params: { page: 1 } })
I get the same result:
[vue-router] missing param for named route "BeatsCatalog": Expected "page" to be defined.
Router:
{
path: '/beats',
components: {
navbar: Navbar,
default: { template: `<router-view/>` }
},
children: [{
name: 'BeatsCatalog',
path: 'catalog/:page',
components: {
default: () => import('#/views/BeatsCatalog')
},
props: { default: true }
},
{
path: 'upload',
name: 'BeatsUpload',
components: {
default: () => import('#/views/BeatsUpload')
}
},
],
meta: { requiresAuth: true }
}
What's causing the issue? I see nothing wrong with my setup, I'm doing everything like in the documentation.
Thanks.
#Giacoma,
In your data property on the component BeatsCatalog the page is undefined when initally loaded. Hence you get the error.
So to solve this wrap your router-link in v-if.
Reference for the same error with better explaination is here:
https://github.com/vuejs/vue-router/issues/986