Vuejs stopped rendering components after I added a transition in the children route of my dashboard layout when I checked the error there was no error and no warnings but whenever I am reloading the page the components render, and the same functionality works in the same application in my login layouts children route when I am going in the network I am getting 304 HTTP error
this is my index router
import { createRouter, createWebHistory } from "vue-router";
// importing Dashboard routes
import DashboardRoutes from "./Dashboard/index.js";
import store from "#/store/store.js";
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: "/",
// redirecting the root to the login welcome page
redirect: { name: "login" },
},
{
// creating a group path for all the login pages
path: "/login",
name: "login",
redirect: { name: "welcome" },
component: () => import("../components/Pages/Login/LoginMain.vue"),
//checking the condition if user is logged in or not and redirecting
beforeEnter: (_, _2, next) => {
if (store.state.login.isLoggedIn) {
next("/dashboard");
} else {
next();
}
},
children: [
{
path: "/welcome",
name: "welcome",
component: () =>
import("../components/Pages/Login/Childrens/WelCome.vue"),
},
{
path: "/austria-login",
name: "austria-login",
component: () =>
import("../components/Pages/Login/Childrens/AustriaLogin.vue"),
},
{
path: "/sms-login",
name: "sms-login",
component: () =>
import("../components/Pages/Login/Childrens/SmsLogin.vue"),
},
{
path: "/enter-tpn",
name: "enter-tpn",
component: () =>
import("../components/Pages/Login/Childrens/EnterTpn.vue"),
//chcking the condition of phone and social security token is entered
beforeEnter: (_, _2, next) => {
if (!store.state.login.phoneVerified) {
next("/sms-login");
} else {
next();
}
},
},
],
},
// using Dashboard Routes
...DashboardRoutes,
],
scrollBehavior(_, _2, savedPosition) {
if (savedPosition) {
window.scrollTo(savedPosition);
} else {
window.scrollTo(0, 0);
}
},
});
export default router;
this is my dashboard children routes
import AppointmentRoutes from "./Appointment"; // importing appointment children routes
import SettingRoutes from "./Setting";
import store from "#/store/store";
const DashboardRoutes = [
{
// router group for all the dashboard views
path: "/dashboardMain",
name: "dashboardMain",
component: () => import("../../components/Pages/DashBoard/IndexMain.vue"),
beforeEnter: (_, _2, next) => {
if (store.state.login.isLoggedIn) {
next();
} else {
next('/login');
}
},
children: [
{
path: "/dashboard",
name: "dashboard",
component: () =>
import("../../components/Pages/DashBoard/Home/DashBoard.vue"),
props: { sidebar: true },
},
// router for appointments
{
path: "/appointments",
name: "PatientAppoinetments",
redirect: { name: "PatientAppointmentsData" },
component: () =>
import(
"../../components/Pages/DashBoard/PatientAppointment/PatientAppointment.vue"
),
props: { sidebar: true },
// children group for appointments components
children: [...AppointmentRoutes],
},
{
path: "/requests",
name: "Requests",
component: () =>
import(
"../../components/Pages/DashBoard/PatientRequests/PatientRequest.vue"
),
},
{
path: "/medications",
name: "Medications",
component: () =>
import(
"../../components/Pages/DashBoard/PatientMedication/PatientMedication.vue"
),
},
{
path: "/questions",
name: "Questions",
component: () =>
import(
"../../components/Pages/DashBoard/PatientQuestionaries/PatientQuestionaries.vue"
),
},
{
path: "/health-status",
name: "HealthStatus",
component: () =>
import(
"../../components/Pages/DashBoard/PatientHealth/PatientHealth.vue"
),
},
{
path: "/diagnostic-center",
name: "PatientDiagnosticCenter",
component: () =>
import(
"../../components/Pages/DashBoard/PatientDiagnostic/PatientDiagnosticCenter.vue"
),
},
{
path: "/vaccination",
name: "PatientVaccination",
component: () =>
import(
"../../components/Pages/DashBoard/PatientVaccination/PatientVaccination.vue"
),
},
{
path: "/setting",
name: "Setting",
redirect: { name: "AccountSetting" },
component: () =>
import("#/components/Pages/DashBoard/Setting/SettingIndex.vue"),
children: [...SettingRoutes],
},
{
path: "/chat",
name: "PatientChat",
redirect: { path: "/chat/gautam" },
component: () =>
import(
"../../components/Pages/DashBoard/PatientChat/PatientChat.vue"
),
// children group for chat page
children: [
{
path: "/chat/:name",
name: "chatMessages",
component: () =>
import(
"../../components/Pages/DashBoard/PatientChat/Children/PatientChatmessages.vue"
),
},
],
},
{
path: "/access-log",
name: "AccessLog",
component: () =>
import("#/components/Pages/DashBoard/AccessLog/AccessLog.vue"),
},
{
path: "/my-profile",
name: "MyProfile",
component: () =>
import("#/components/Pages/DashBoard/MyProfile/MyProfile.vue"),
props: { sidebar: true },
},
],
},
];
export default DashboardRoutes;
and this is DahboardMain where i want to renders my dashboard children pages
but i am getting the blank the black screen children area whenere i am going to any route except page reload
I tried to remove beforeEnter guard from the routes and I also removed all the code from the dashboard layout except router-view but still getting the black screen
enter image description here this is the image of the blank screen
enter image description here this is showing in the network
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.
I have a grpc application, there is authorization. When you start a project, you must be logged in. I decided to add under the login button if you are not registered. But the router does not work. Only at the entrance, go to the registration page. Please help to understand what is the mistake? Why is seemingly blocked?
routes.js
const routes = [
{
path: "/",
component: () => import("layouts/MainLayout"),
children: [
{
path: "",
component: () => import("pages/Index"),
meta: { requireAuth: true }
},
{
path: "/logs",
component: () => import("pages/Logs"),
meta: { requireAuth: true, admin: true }
}
]
},
{
path: "/",
component: () => import("layouts/AuthLayout"),
children: [
{
path: "/welcome",
component: () => import("pages/Auth"),
meta: { guest: true }
},
{
path: "/register",
component: () => import("pages/Register"),
meta: { guest: true }
}
]
}
];
I tried many things, like in Auth.vue:
<q-item to='/register'>Sign Up</q-item>
<router-link tag="a" :to="{path:'/register'}" replace>Go</router-link>
<span #click="callSomeFunc()">Register</span>
...
methods: {
callSomeFunc() {
this.$router.push({ path: "/register" });
}
My router-view in App.vue
for more information github repo
You have duplicate routes in your config - the path / is used on 2 routes. You should fix this.
To prevent unauthorized users to see your protected pages you can add a global navigation guard to your router through the beforeEach hook:
import VueRouter from 'vue-router';
const routes = [
{
path: "/",
component: () => import("layouts/MainLayout"),
meta: { requireAuth: true },
children: [
{
path: "",
component: () => import("pages/Index"),
},
{
path: "logs",
component: () => import("pages/Logs"),
meta: { admin: true }
}
]
},
{
path: "/login",
component: () => import("layouts/AuthLayout"),
children: [
{
path: "",
component: () => import("pages/Auth"),
},
{
path: "/register",
component: () => import("pages/Register"),
}
]
}
];
const router = new VueRouter({
routes
});
router.beforeEach((to, from, next) =>
{
if (to.matched.some(route => route.meta.requireAuth))
{
if (userNotLogged) next('/login');
else next();
}
else next();
});
export default router;
You may also consider reading a more verbose tutorial, e.g. https://www.digitalocean.com/community/tutorials/how-to-set-up-vue-js-authentication-and-route-handling-using-vue-router
In my app I have a registred area, when you login successfully a global variable "auth" will take the value loggedin, in my main vue component App.vue I load the header component which include the navbar and the router view
I call the created function in the header component to read the value of "auth" to show the login link and hide the profile,chat and logout links
I also want to use the sema method in some router views (char and profile) to prevent the user to get acces to them and push the router to the login page when the "auth" variable is not loggedin.
In that case, the App.vue have to run the created function twice, the header component reads correctly the value of "auth" while the router view does not.
Is there any solution to do that? or any alternative to prevent the access to the registred area without login ?
update
I have tried vuex and I got this error (Cannot read property 'commit' of undefined)
and the store.state.auth still have the value of false
this is my login component
<script>
/* eslint-disable */
import axios from 'axios'
import router from '../router'
import EventBus from './EventBus.vue'
export default {
data () {
return {
email: '',
password: '',
error: ''
}
},
methods: {
login () {
axios.post('users/login', {
email: this.email,
password: this.password
}).then(res => {
console.log('user exist ')
localStorage.setItem('usertoken', res.data)
this.email = ''
this.password = ''
router.push({ name: 'Profile' })
this.$store.commit('login') // sets auth to true
this.emitMethod()
}).catch(err => {
console.log(err.message)
this.error = ('User does not exist ')
this.email = ''
this.password = ''
})
},
onReset(evt) {
evt.preventDefault()
// Reset our form values
this.email = ''
this.password = ''
// Trick to reset/clear native browser form validation state
this.show = false
this.$nextTick(() => {
this.show = true
})
},
emitMethod () {
EventBus.$emit('logged-in', 'loggedin')
}
}
}
</script>
and here is main.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import AllIosIcon from 'vue-ionicons/dist/ionicons-ios.js'
import Vuex from 'vuex'
/* eslint no-console: ["error", { allow: ["warn", "error"] }] */
Vue.use(Vuex)
Vue.use(AllIosIcon)
Vue.use(VueRouter)
const store = new Vuex.Store({
state: {
auth: false
},
mutations: {
login: (state) => state.auth = true,
logout: (state) => state.auth = false
}
})
const routes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/products',
name: 'products',
component: () => import( '../views/Products.vue')
},{
path: '/spareParts',
name: 'spareParts',
component: () => import( '../views/SpareParts.vue')
},
{
path: '/contact',
name: 'contact',
component: () => import( '../views/Contact.vue')
},
{
path: '/login',
name: 'login',
component: () => import( '../views/logIn.vue')
},
{
path: '/About',
name: 'About',
component: () => import( '../views/About.vue')
},
{
path: '/Profile',
name: 'Profile',
component: () => import( '../views/Profile.vue'),
meta: {
requiresAuth: true
}
},
{
path: '/Chat',
name: 'Chat',
component: () => import( '../views/Chat.vue'),
meta: {
requiresAuth: true
}
},
{
path: '/Spare1',
name: 'Spare1',
component: () => import( '../views/Spare1.vue')
},
{
path: '/spare2',
name: 'spare2',
component: () => import( '../views/spare2.vue')
},
{
path: '/spare3',
name: 'spare3',
component: () => import( '../views/spare3.vue')
},
{
path: '/spare4',
name: 'spare4',
component: () => import( '../views/spare4.vue')
},
{
path: '/spare5',
name: 'spare5',
component: () => import( '../views/spare5.vue')
},
{
path: '/spare6',
name: 'spare6',
component: () => import( '../views/spare6.vue')
},
{
path: '/spare7',
name: 'spare7',
component: () => import( '../views/spare7.vue')
},
{
path: '/spare8',
name: 'spare8',
component: () => import( '../views/spare8.vue')
},
{
path: '/spare9',
name: 'spare9',
component: () => import( '../views/spare9.vue')
},
{
path: '/spare10',
name: 'spare10',
component: () => import( '../views/spare10.vue')
},
{
path: '/spare11',
name: 'spare11',
component: () => import( '../views/spare11.vue')
},
{
path: '/spare12',
name: 'spare12',
component: () => import( '../views/spare12.vue')
},
{
path: '/spare13',
name: 'spare13',
component: () => import( '../views/spare13.vue')
},
{
path: '/spare14',
name: 'spare14',
component: () => import( '../views/spare14.vue')
},
{
path: '/spare15',
name: 'spare15',
component: () => import( '../views/spare15.vue')
},
{
path: '/spare16',
name: 'spare16',
component: () => import( '../views/spare16.vue')
},
{
path: '/spare17',
name: 'spare17',
component: () => import( '../views/spare17.vue')
},
{
path: '/spare18',
name: 'spare18',
component: () => import( '../views/spare18.vue')
},
{
path: '/spare19',
name: 'spare19',
component: () => import( '../views/spare19.vue')
},
{
path: '/spare20',
name: 'spare20',
component: () => import( '../views/spare20.vue')
},
{
path: '/spare21',
name: 'spare21',
component: () => import( '../views/spare21.vue')
},
{
path: '/spare22',
name: 'spare22',
component: () => import( '../views/spare22.vue')
},
{
path: '/spare23',
name: 'spare23',
component: () => import( '../views/spare23.vue')
},
{
path: '/product1',
name: 'product1',
component: () => import( '../views/product1.vue')
},
{
path: '/freezer',
name: 'freezer',
component: () => import( '../views/freezer.vue')
},
{
path: '/construction',
name: 'construction',
component: () => import( '../views/construction.vue')
},
{
path: '/product2',
name: 'product2',
component: () => import( '../views/product2.vue')
},
{
path: '/earth',
name: 'earth',
component: () => import( '../views/earth.vue')
},
{
path: '/crawler',
name: 'crawler',
component: () => import( '../views/crawler.vue')
},
{
path: '/articulated',
name: 'articulated',
component: () => import( '../views/articulated.vue')
},
{
path: '/wheel',
name: 'wheel',
component: () => import( '../views/wheel.vue')
},
{
path: '/tractor',
name: 'tractor',
component: () => import( '../views/tractor.vue')
},
{
path: '/telescopic',
name: 'telescopic',
component: () => import( '../views/telescopic.vue')
},
{
path: '/loader',
name: 'loader',
component: () => import( '../views/loader.vue')
},
{
path: '/pipe',
name: 'pipe',
component: () => import( '../views/pipe.vue')
},
{
path: '/pontoon',
name: 'pontoon',
component: () => import( '../views/pontoon.vue')
},
{
path: '/duty',
name: 'duty',
component: () => import( '../views/duty.vue')
},
{
path: '/attachment',
name: 'attachment',
component: () => import( '../views/attachment.vue')
},
{
path: '/customer',
name: 'customer',
component: () => import( '../views/customer.vue')
},
{
path: '/side',
name: 'side',
component: () => import( '../views/side.vue')
},
{
path: '/wine',
name: 'wine',
component: () => import( '../views/wine.vue')
},
{
path: '/accessories',
name: 'accessories',
component: () => import( '../views/accessories.vue')
},
{
path: '/hotel',
name: 'hotel',
component: () => import( '../views/hotel.vue')
},
{
path: '/bakery',
name: 'bakery',
component: () => import( '../views/bakery.vue')
},
{
path: '/retail',
name: 'retail',
component: () => import( '../views/retail.vue')
},
{
path: '/industry',
name: 'industry',
component: () => import( '../views/industry.vue')
},
{
path: '/mining',
name: 'mining',
component: () => import( '../views/mining.vue')
},
{
path: '/mobile',
name: 'mobile',
component: () => import( '../views/mobile.vue')
},
{
path: '/material',
name: 'material',
component: () => import( '../views/material.vue')
},
{
path: '/maritime',
name: 'maritime',
component: () => import( '../views/maritime.vue')
},
{
path: '/aero',
name: 'aero',
component: () => import( '../views/aero.vue')
},
{
path: '/gear',
name: 'gear',
component: () => import( '../views/gear.vue')
},
{
path: '/combust',
name: 'combust',
component: () => import( '../views/combust.vue')
},
{
path: '/hotelgroup',
name: 'hotelgroup',
component: () => import( '../views/hotelgroup.vue')
},
{
path: '/deep',
name: 'deep',
component: () => import( '../views/deep.vue')
},
{
path: '/tower',
name: 'tower',
component: () => import( '../views/tower.vue')
},
{
path: '/concrete',
name: 'concrete',
component: () => import( '../views/concrete.vue')
},
{
path: '/problem',
name: 'problem',
component: () => import( '../views/problem.vue')
}
]
const router = new VueRouter({
routes // short for routes: routes
})
router.beforeEach((to, from, next) => {
console.error(store.state.auth)
if (to.meta.requiresAuth && !store.state.auth) {
// this route requires auth, check if logged in
// if not, redirect to login page.
next({ name: 'login' })
} else {
next() // does not require auth, make sure to always call next()!
}
})
export default router; store
updated
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import BootstrapVue from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import AllIosIcon from 'vue-ionicons/dist/ionicons-ios.js'
import i18n from './i18n'
import store from './router'
Vue.use(AllIosIcon)
Vue.use(BootstrapVue)
Vue.config.productionTip = false
new Vue({
router,
i18n,
store,
render: h => h(App)
}).$mount('#app')
now I got this error
_this.$store.commit is not a function
In my opinion, the best way to handle this is to use vuex for state management and vue-router's navigation guards.
Look at the code below to understand how this might be done.
main.js
import Vue from 'vue'
import Vuex from 'vuex'
import VueRouter from 'vue-router'
Vue.use(Vuex)
Vue.use(VueRouter)
const store = new Vuex.Store({
state: {
auth: false
},
mutations: {
login: (state) => state.auth = true,
logout: (state) => state.auth = false
}
})
const router = new VueRouter({
mode: 'history',
routes: [
{
path: '/dashboard',
component: Dashboard,
name: 'dashboard',
meta: {
requiresAuth: true
}
},
{
path: '/login',
component: Login,
name: 'login',
},
]
})
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !store.state.auth) {
next({
path: '/login',
query: {
redirectTo: to.path
}
})
}
next()
})
const app = new Vue({
el: '#app',
store,
router
})
What we are doing here is setting up a central source of truth for the auth status of a user. The beforeEach navigation guard is run before entering a route. In this case we are checking if the route requires authentication (using the requiresAuth metadata). If the route requires authentication and you're not logged in, it will redirect you to a login page.
Your login page, should have logic that logs in the user and sets the authentication state to true.
Login.vue
<template>
// ...
</template>
<script>
export default {
methods: {
login() {
// login logic here
// after successful login
this.$store.commit('login') // sets auth to true
}
}
}
</script>
This might involve more process but you end up with better results at the end of the day.