VueJS is asking to login every i'm open in new tab - javascript

i wanna ask about my code, by the way, i'm really new in vue.js so, i wanna ask about this unusual behaviour i've ever meet.
When i've logged in, and then open the url in new tab, it's ask me to login again.
it's always ask me to do login every i open in new tab. am i missed something?
here is my store.js, auth.js and router.js
store.js
import Vue from "vue";
import Vuex from "vuex";
import auth from "./stores/auth.js";
import user from "./stores/user.js";
Vue.use(Vuex);
const store = new Vuex.Store({
modules: {
auth,
user
},
state: {
admin_id: sessionStorage.getItem("admin_id"),
token: sessionStorage.getItem("token"),
errors: [],
msg: [],
user_lists: [],
role_lists: [],
user_data: [],
show_spinner: false,
},
getters: {
isAuth: state => {
return state.token != "null" && state.token != null;
}
},
mutations: {
SET_TOKEN(state, payload) {
state.token = payload;
},
SET_ADMIN_ID(state, payload) {
state.admin_id = payload;
},
SET_ERRORS(state, payload) {
state.errors = payload;
},
SET_MSG(state, payload) {
state.msg = payload;
},
CLEAR_ERRORS(state) {
state.errors = [];
},
ASSIGN_USER_LIST(state, payload) {
state.user_lists = payload
},
ASSIGN_ROLE_LIST(state, payload) {
state.role_lists = payload
},
GET_USER_DATA(state, payload) {
state.user_data = payload;
},
SHOW_SPINNER(state, payload) {
state.show_spinner = payload;
},
}
});
export default store;
auth.js
import $axios from "../api.js";
const state = () => ({});
const mutations = {};
const actions = {
submitlogin({ commit }, payload) {
return new Promise((resolve, reject) => {
$axios
.post("/auth/login", payload)
.then(response => {
if (response.data.status == "success") {
sessionStorage.setItem("token", response.data.token);
sessionStorage.setItem(
"userdata",
JSON.stringify(response.data.userdata)
);
sessionStorage.setItem('admin_id', response.data.userdata[0].user_id)
commit("SET_TOKEN", sessionStorage.getItem("token"), {
root: true
});
commit("SET_ADMIN_ID", sessionStorage.getItem('admin_id'), {
root: true
});
} else {
commit(
"SET_ERRORS",
{ invalid: response.data.msg },
{ root: true }
);
}
resolve(response.data);
})
.catch(error => {
if (error.response.status == 422) {
commit(
"SET_ERRORS",
{ invalid: error.response.msg },
{
root: true
}
);
}
});
});
},
submitlogout({ commit }) {
return new Promise((resolve, reject) => {
$axios
.post("/auth/logout")
.then(response => {
if (response.data.status == "success") {
sessionStorage.removeItem("token");
sessionStorage.removeItem("userdata");
commit("SET_TOKEN", null, {
root: true
});
}
resolve(response.data);
})
.catch(error => {});
});
},
};
export default {
namespaced: true,
state,
actions,
mutations
};
router.js
import Vue from "vue";
import Router from "vue-router";
import store from "./store.js";
import Home from "./pages/DashboardPage";
import Login from "./pages/Login";
import Logout from "./pages/Logout";
import User from "./pages/User";
import UserList from "./pages/UserList";
import AddUser from "./pages/AddUser";
import EditUser from "./pages/EditUserData";
import Profile from "./pages/Profile";
Vue.use(Router);
//DEFINE ROUTE
const router = new Router({
mode: "history",
linkExactActiveClass: "active",
routes: [
{
path: "/",
name: "home",
component: Home,
meta: {
requiresAuth: true
}
},
{
path: "/user/",
name: "user",
component: User,
meta: {
requiresAuth: true
}
},
{
path: "/user/list",
name: "userlist",
component: UserList,
meta: {
requiresAuth: true
}
},
{
path: "/user/tambah",
name: "adduser",
component: AddUser,
meta: {
requiresAuth: true
}
},
{
path: "/user/edit/:id",
name: "edituser",
component: EditUser,
meta: {
requiresAuth: true
}
},
{
path: "/profile",
name: "edituser",
component: Profile,
meta: {
requiresAuth: true
}
},
{
path: "/login",
name: "login",
component: Login
},
{
path: "/logout",
name: "logout",
component: Logout
}
]
});
//Navigation Guards
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
let auth = store.getters.isAuth;
if (!auth) {
next({
name: "login"
});
} else {
next();
}
} else {
next();
}
});
export default router;
i've tried to use localStorage to store the token, but also it's seems not working.
every feedback or suggestion are appreciated. Thank You.
ps : sorry for bad english...

This is a known issue. Vuex state is not persistent. So you need to install and use
vuex-persistedstate https://www.npmjs.com/package/vuex-persistedstate
I hope this helps. Let me know if you have any questions.
Thanks.

Related

Vuejs fill <component> with dynamic params in url

I want to use routes.js for dynamic components that I send in params of urls.
Like this:
let routes=[
{
path: "",
component: LayoutDashboard,
children: [
{
path: '',
component: Dashboard
},
{
path: '/:pageName/:subPageName',
component: ()=>import('./pages/plugins/'+route.params.pageName+'/'+route.params.subPage)
}
]
}];
Vue.js version is 3
In above code, I can't use route.params.subPage or this.route.params.subPage.
How can I do it?
Of course I use like like below code. but it doesn't work.
let routes=[
{
path: "",
component: LayoutDashboard,
children: [
{
path: '',
component: Dashboard
},
{
path: '/:pageName/:subPageName',
component: Controller
}
]
};
Controller.vue code is:
<template>
<component :is="getCurrentComponent"/>
</template>
<script>
export default {
data()
{
return {
pageName:this.$route.params.pageName,
subPageName:this.$route.params.subPageName
}
},
created()
{
},
methods:{
getCurrentComponent()
{
return ()=>import("./plugins/"+this.pageName+"/"+this.subPageName);
}
}
}
</script>
Result of solution 2 is:
Red line content is that component.
I searched and found the answer.
We can use two ways:
Routes.js:
export const routes=[
{
path: "",
component: LayoutDashboard,
children: [
{
path: '',
component: Dashboard,
exact: true
},
{
path: '/:pageName/:subPageName',
component: Controller
}
]
}
];
Method 1 (Controller.vue):
<template>
<component :is="currentComponent"/>
</template>
<script>
export default {
data()
{
return {
pageName:this.$route.params.pageName,
subPageName:this.$route.params.subPageName,
currentComponent:null
};
},
created()
{
this.loadComponent();
},
watch:{
$route (to, from){
this.pageName=to.params.pageName;
this.subPageName=to.params.subPageName;
this.loadComponent();
}
},
methods:{
loadComponent()
{
new Promise(resolve => {
import("./plugins/"+this.pageName+"/"+this.subPageName).then((c) =>{
this.currentComponent=c.default;
resolve(c.default);
}).catch(e=>{
console.log(e);
})
})
}
}
}
</script>
Method 2 (Controller.vue):
<template>
<component :is="currentComponent"/>
</template>
<script>
import {defineAsyncComponent} from "vue";
export default {
data()
{
return {
pageName:this.$route.params.pageName,
subPageName:this.$route.params.subPageName,
currentComponent:null
};
},
created()
{
this.loadComponent();
},
watch:{
$route (to, from){
this.pageName=to.params.pageName;
this.subPageName=to.params.subPageName;
this.loadComponent();
}
},
methods:{
loadComponent()
{
this.currentComponent=defineAsyncComponent(
()=>import("./plugins/"+this.pageName+"/"+this.subPageName)
);
}
}
}
</script>

Vue router doesn't recognize :lang as a param

I have the following code:
import Router from 'vue-router';
let mainRoutes = [
{path: '/first', component: () => import('./pages/First')},
{path: '/second', component: () => import('./pages/Second')},
{path: '/third', component: () => import('./pages/Third')},
];
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
scrollBehavior() {
return {x: 0, y: 0}
},
routes: [
{
path: '/:lang',
component: () => import('./layouts/Main'),
children: mainRoutes,
meta: {requiresAuth: true, permissions: true}
},
{
path: '*',
component: () => import('#/pages/errors/404')
}
]
})
router.beforeEach((to, from, next) => {
if (!to.query.lang) {
to.query.lang= 'ru';
next({ path: to.path, query: to.query });
} else {
next();
}
});
export default router
What I want:
Every time some route is entered, I want the vue-router to check whether it has the lang param or not. If not, I want it to place 'ru' in there, if yes then proceed and show the page with the necessary lang (the part which i18n is responsible for).
The problem is that it doesn't recognize ':lang' as a param for the children routes for some reason, so if I try to go to 'test.test/ru', it returns the lang param ok, but if I try 'test.test/ru/first' it doesn't see it and returns 404.
Everything works in case I put :lang param before every child component but it's not really practical. Is there any better way to solve this issue?
With a code like this you should get the effect you want.
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import VueRouter from 'vue-router';
import Router from './Router.vue';
import En from './translation/En.vue';
import Ru from './translation/Ru.vue';
Vue.use(VueI18n);
Vue.use(VueRouter);
Vue.use(VueBus);
const messages = {
en: En,
ru: Ru,
};
const i18n = new VueI18n({
fallbackLocale: 'ru',
locale: 'ru',
messages,
});
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/:lang',
component: {
render: (h) => h('router-view'),
},
children: [your children route],
});
router.beforeEach((to, from, next) => {
const { lang } = to.params;
if (!['en', 'fr'].includes(lang)) {
return next(i18n.locale);
}
if (i18n.locale !== lang) {
i18n.locale = lang;
}
return next();
});
I'm not sure but without i18n I think it's that :
...
router.beforeEach((to, from, next) => {
const { lang } = to.params;
if (!['en', 'ru'].includes(lang)) {
route.params.lang = 'ru';
router.push({ name: route.name });
}
});
I've finally found a solution!
If you have some param in the main route, your children routes shouldn't start with a '/' symbol, but simply with the correct route, for instance
let mainRoutes = [
{path: 'first', component: () => import('./pages/First')},
{path: 'second', component: () => import('./pages/Second')},
{path: 'third', component: () => import('./pages/Third')},
];
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
scrollBehavior() {
return {x: 0, y: 0}
},
routes: [
{
path: '/:lang',
component: () => import('./layouts/Main'),
children: mainRoutes,
meta: {requiresAuth: true, permissions: true}
},
]
})

Vue Router should not redirect if user is logged in

I use Firebase auth with Vuejs and Vue Router.
I have the pages Home, Login, SignUp and Tasks.
I want that when the user is logged in and goes to the Login or SignUp page he will get redirected to the Tasks page but if he goes to the Home page he should not get redirected to the Tasks page. I don't know how to configure this and ask for help.
I have the following code:
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/signup',
name: 'SignUp',
component: SignUp
},
{
path: '/tasks',
name: 'Tasks',
component: Tasks,
meta: {
requiresAuth: true
}
},
{ path: "*", redirect: {path: '/'} }
]
const router = new VueRouter({
mode: "history",
routes
});
router.beforeEach((to, from, next) => {
const currentUser = firebase.auth().currentUser;
const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
if (requiresAuth && !currentUser) next('login');
else if (!requiresAuth && currentUser){next('tasks')}
else next();
});
let app;
firebase.auth().onAuthStateChanged(function () {
if(!app){
new Vue({
router,
render (h) {
return h(App)
}
}).$mount('#app');
}
});
Solution
I have added a meta tag to the Home path and added an if clause in the router function.
Solution code :
const routes = [
{
path: '/',
name: 'Home',
component: Home,
// I added this meta tag to the Home path.
meta: {
loggedin: true
}
},
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/signup',
name: 'SignUp',
component: SignUp
},
{
path: '/tasks',
name: 'Tasks',
component: Tasks,
meta: {
requiresAuth: true
}
},
{ path: "*", redirect: {path: '/'} }
]
const router = new VueRouter({
mode: "history",
routes
});
router.beforeEach((to, from, next) => {
const currentUser = firebase.auth().currentUser;
const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
const loggedin = to.matched.some(record => record.meta.loggedin);
// I added the if clause under this text.
if (loggedin && currentUser) next();
else if (requiresAuth && !currentUser) next('login');
else if (!requiresAuth && currentUser) next('tasks');
else next();
});
let app;
firebase.auth().onAuthStateChanged(function () {
if(!app){
new Vue({
router,
render (h) {
return h(App)
}
}).$mount('#app');
}
});

Vue Router - Paths being concatenated multiple times

I am facing problems with the Vue Router and I have no idea what is causing this...
When my application loads it inserts the page path twice.
Example:
If I access the path http://localhost:8080/painel it will be shown in the browser the following path: http://localhost:8080/painel/painel
If I refresh the page the path will be added one more time, going like this: http://localhost:8080/painel/painel/painel
MY files:
/src/main.js
import Vue from 'vue'
import localforage from 'localforage'
import Notifications from 'vue-notification'
import App from './App'
import store from './store'
import router from './router'
import bus from './support/bus'
import http from './support/http'
Vue.config.productionTip = true
window._ = require('lodash')
localforage.config({
driver: localforage.LOCALSTORAGE,
storeName: 'invenio-center'
})
store.dispatch('auth/setToken').then(() => {
store.dispatch('auth/fetchSystemData').catch(() => {
store.dispatch('auth/clearAuth')
})
}).catch(() => {
store.dispatch('auth/clearAuth')
})
Vue.use(Notifications)
Vue.use(bus)
Vue.use(http)
new Vue({
el: '#app',
router,
store,
components: {App},
template: '<App/>'
})
/src/router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import store from '../store'
import Login from '../pages/Login'
import Panel from '../pages/Panel'
import PanelIndex from '../pages/panel/Index'
Vue.use(Router)
const router = new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'login',
component: Login,
meta: {
visitor: true
}
},
{
path: 'painel',
component: Panel,
meta: {
auth: true
},
children: [
{
path: '/',
name: 'panel.index',
component: PanelIndex
},
{
path: 'idr',
name: 'panel.idr',
component: PanelIndex
}
]
},
{
path: "*",
redirect: {
name: 'panel.index'
},
component: PanelIndex
}
]
})
router.beforeEach(
(to, from, next) => {
store.dispatch('auth/setToken').then(() => {
if(to.meta.visitor){
next({
name: 'panel.index'
});
return;
}
next();
}).catch(() => {
if(to.meta.auth){
next({
name: 'login'
});
return;
}
next();
})
}
)
export default router
/src/pages/Panel.vue
<template>
<div class="panel-container">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'Panel',
data() {
return {
}
}
}
</script>
<style lang="scss" scoped>
.panel-container {
}
</style>
/src/pages/panel/Index.vue
<template>
<div class="index-container">index</div>
</template>
<script>
export default {
name: 'PanelIndex',
data() {
return {
}
}
}
</script>
<style lang="scss" scoped>
.index-container {
}
</style>
try this, add / before path: '/painel', and do that for other components.
/ is used to distinct from relative path.

My global Components are not available

I am new to vuex so i might have only a really dumb mistake.
I am trying to make a reactive Router, for that i used the store from vuex and since i have multiple Components i used a selfwritten Plugin to make them all global. My problem is that the store, where all the routes are saved,and all other components dont have access to the components i set global. I get the following Errormessage:
Uncaught ReferenceError: Home is not defined
my Plugin to make the components global
componentPlugin.js:
import List from "./components/List.vue";
import MainMenu from "./components/MainMenu.vue";
import Test from "./views/Test.vue";
import About from "./views/About.vue";
import Menu from "./views/Menu.vue";
import Home from "./views/Home.vue";
export default {
install(Vue) {
Vue.component("List", List);
Vue.component("MainMenu", MainMenu);
Vue.component("Test", Test);
Vue.component("About", About);
Vue.component("Menu", Menu);
Vue.component("Home", Home);
}
};
my store.js:
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
projects: [{ id: 0, title: "Create new Project", compRate: 0 }],
globalid: 1,
projectname: "",
routes: [
{
path: "/home",
name: "home",
component: Home
},
{
path: "/about",
name: "about",
component: About
},
{
path: "/menu",
name: "menu",
component: Menu
}
],
reloaded: 0
},
mutations: {
newProject: (state, project) => {
state.projects.push({
id: project.id,
title: project.title,
compRate: project.compRate
});
},
delProject: (state, id) => {
state.projects.forEach(e => {
if (id === e.id) {
state.projects.splice(state.projects.indexOf(e), 1);
}
});
},
newName: (state, name) => {
state.projectname = name;
},
newRoute: state => {
state.reloaded++;
}
},
actions: {
newProject: ({ commit, state }, project) => {
commit("newProject", {
id: state.globalid,
title: project.title,
compRate: project.compRate
});
state.globalid++;
},
delProject: ({ commit }, id) => {
commit("delProject", id);
},
newRoute: ({ commit }) => {
commit("newRoute");
}
},
getters: {
getProjectNumber(state) {
return state.projects.length;
},
getReloaded(state) {
return state.reloaded;
}
}
});
My main.js:
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
import storePlugin from "./storePlugin";
Vue.use(storePlugin);
import componentPlugin from "./componentPlugin.js";
Vue.use(componentPlugin);
import "./registerServiceWorker.js";
import App from "./App.vue";
import router from "./router.js";
import store from "./store.js";
import BootstrapVue from "bootstrap-vue";
import "bootstrap/dist/css/bootstrap.css";
import "bootstrap-vue/dist/bootstrap-vue.css";
Vue.use(BootstrapVue);
new Vue({
router,
store,
render: h => h(App)
}).$mount("#app");
The storePlugin is just to make the store global
storePlugin:
import store from "./store";
export default {
store,
install(Vue) {
Vue.prototype.$myStore = store;
}
};
I am using Vue v2.5.17 and vue-router 2.0.
If you need more information, just ask but im pretty sure that this is all that matters.
When you call
import storePlugin from "./storePlugin";
Vue.use(storePlugin);
in main.js your Vue instance doesn't know about the componentPlugin and what it does because it's called after storePlugin (in storePlugin you import the store so there is where I suspect you get the ReferenceError)
Try this:
main.js
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
import componentPlugin from "./componentPlugin.js";
Vue.use(componentPlugin);
import storePlugin from "./storePlugin";
Vue.use(storePlugin);
import "./registerServiceWorker.js";
import App from "./App.vue";
import router from "./router.js";
import store from "./store.js";
import BootstrapVue from "bootstrap-vue";
import "bootstrap/dist/css/bootstrap.css";
import "bootstrap-vue/dist/bootstrap-vue.css";
Vue.use(BootstrapVue);
new Vue({
router,
store,
render: h => h(App)
}).$mount("#app");
store.js
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
projects: [{ id: 0, title: "Create new Project", compRate: 0 }],
globalid: 1,
projectname: "",
routes: [
{
path: "/home",
name: "home",
component: Vue.component('Home')
},
{
path: "/about",
name: "about",
component: Vue.component('About')
},
{
path: "/menu",
name: "menu",
component: Vue.component('Menu')
}
],
reloaded: 0
},
mutations: {
newProject: (state, project) => {
state.projects.push({
id: project.id,
title: project.title,
compRate: project.compRate
});
},
delProject: (state, id) => {
state.projects.forEach(e => {
if (id === e.id) {
state.projects.splice(state.projects.indexOf(e), 1);
}
});
},
newName: (state, name) => {
state.projectname = name;
},
newRoute: state => {
state.reloaded++;
}
},
actions: {
newProject: ({ commit, state }, project) => {
commit("newProject", {
id: state.globalid,
title: project.title,
compRate: project.compRate
});
state.globalid++;
},
delProject: ({ commit }, id) => {
commit("delProject", id);
},
newRoute: ({ commit }) => {
commit("newRoute");
}
},
getters: {
getProjectNumber(state) {
return state.projects.length;
},
getReloaded(state) {
return state.reloaded;
}
}
});
If you want to use the router in vuex I recommend vuex-router-sync

Categories

Resources