How to link routes list with store variable? - vue.js

Is there any way to link routes list:
// router.js
export default new Router({
routes: [
{ path: '/', component: Page },
{ path: '/page1', component: Page1 },
{ path: '/page2', component: Page2 },
]
})
...to the variable in store:
// store.js
export default new Vuex.Store({
state: {
routes_list: []
}
})
?

You would need to add a getter for your list. Something like:
export default new Vuex.Store({
state: {
routes_list: []
},
getters: {
routesList: state => {
return state.routes_list;
}
}
})
Then you could import your Store in your router.js and use the created getter to receive the list:
// maybe your path is different
import Store from '#/store/index';
export default new Router({
routes: Store.getters.routesList
})
I've didn't tested the router code, maybe you need to do some correction.

Related

Accessing to store in the router

I would like to check in my Vuex store whether a user has the 'admin' role before entering the /dashboard route. But I can't properly access data from store.getters.
I use Quasar (Vue.js) and Vuex + Typescript.
In the routes.ts file, on the beforeEnter() function, I can access getters from the store with a console.log(store.myStore.getters). Here I see userInfos inside:
I don't understand why I only get {} and not {...} (Note that if I click on it, I see its contents).
But if I call console.log(store.myStore.getters.userInfos), I don't see the data:
Here is index.ts (router):
import { route } from 'quasar/wrappers'
import VueRouter from 'vue-router'
import { Store } from 'vuex'
import { StateInterface } from '../store'
import routes from './routes'
export default route<Store<StateInterface>>(function ({ Vue }) {
Vue.use(VueRouter)
const Router = new VueRouter({
scrollBehavior: () => ({ x: 0, y: 0 }),
routes,
mode: process.env.VUE_ROUTER_MODE,
base: process.env.VUE_ROUTER_BASE
})
return Router
})
Here is routes.ts (router):
import { RouteConfig } from 'vue-router'
const routes: RouteConfig[] = [
{
path: '/',
component: () => import('layouts/Login.vue'),
children: [
{ path: '', component: () => import('pages/Index.vue') },
{ path: '/inscription', component: () => import('pages/SignUp.vue') },
{ path: '/connexion', component: () => import('pages/SignInPage.vue') }
]
},
{
path: '/main',
component: () => import('layouts/MainLayout.vue'),
children: [
{ path: '', component: () => import('pages/Index.vue') },
{ path: '/dashboard', component: () => import('pages/DashboardB2B.vue'),
beforeEnter: (to, from, next) => {
const store = require('../store')
console.log("before enter")
console.log(store.myStore.getters)
return next();
}, },
{
path: '/ajouter-un-referentiel',
component: () => import('pages/ReferentielMetier.vue')
},
{
path: '/init',
component: () => import('components/bot/BotSkeleton.vue')
}
]
},
{
path: '/bot',
component: () => import('layouts/Bot.vue'),
children: [
{
path: '/ajouter-un-referentiel',
component: () => import('pages/ReferentielMetier.vue')
},
{
path: '/init',
component: () => import('components/bot/BotSkeleton.vue')
}
]
},
// Always leave this as last one,
// but you can also remove it
{
path: '*',
component: () => import('pages/Error404.vue')
}
]
export default routes
And here is index.ts with the store (Vuex):
import Vue from 'vue'
import { store } from 'quasar/wrappers'
import Vuex from 'vuex'
Vue.use(Vuex)
import matching from './modules/matching'
import orga from './modules/organigrame'
import user from './modules/user'
export interface StateInterface {
example: unknown
}
let myStore: any
export default store(function({ Vue }) {
Vue.use(Vuex)
const Store = new Vuex.Store<StateInterface>({
modules: {
matching,
orga,
user
},
// enable strict mode (adds overhead!)
// for dev mode only
strict: !!process.env.DEBUGGING
})
myStore = Store
return Store
})
export {myStore}
EDIT: Looks like my console.log runs before the getters are loaded, because when I check out Vue developer tools, I see everything. How can I check the store if the store itself doesn't load before the beforeEnter function?
please try like this
store.myStore.getters["userInfos"]
I'm having exact issue, even if i use async/await :S
try this
router.beforeEach(async(to, from, next) => {
const userInfo = await store.getters.userInfos;
console.log(userInfo);
});

Vue - Can I change a routers component based on the value of an item in the store?

So I want to change a routers component based on a state in my store. This means that, depending on the state in the store, the router can display a different template page.
Router.js:
import Router from 'vue-router'
import store from './store'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Homepage',
component: () => import('#/' + store.state.theme.path + '/components/Hello')
},
{
path: '/admin',
name: 'Admin',
component: () => import('#/cms/components/Admin')
}
]
})
Store.js:
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
state: {
theme: {
path:'theme-00'
}
},
getters: {
theme: state => {
return state.theme.path;
}
}
});
Any help is welcome!
Thanks,
Justin.

Redirect to specific url in case of wrong url in vuejs

I have two separate routing files where I am importing the component and defining their routing in each of its file and using it in index.js file. Here are my files code:
//router1.js
import Layout1 from 'Layouts/Panel.vue';
const Users = () => import('Views/Users.vue');
const Reports = () => import('Views/Reports.vue');
export default {
path: '/layout1',
component: Layout1,
redirect:'/layout1/reports',
children:[
{
path: 'reports',
component: Reports,
name:'Reports'
},
{
path: 'users',
component: Users,
name:'Users'
}
]
}
//router2.js
import Layout2 from 'Layout/Panel2';
const Demo1 = () => import('Views/Demo1');
const Demo2 = () => import('Views/Demo2');
export default {
path: '/',
component: Layout2,
redirect:'/demo1',
children:[
{
path: '/demo1',
component: Demo1
},
{
path: '/demo2',
component: Demo2
}
]
}
// index.js
import Vue from 'vue'
import Router from 'vue-router'
import router1 from './router1';
import router2 from './router2';
const NotFound = () => import('Views/NotFound.vue');
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
router1,
router2,
{
path: '*',
component: NotFound,
name:'NotFound',
},
]
})
Now, I want to redirect to specific url i.e "not-found" in case of wrong URL. In "NotFound" component I am adding below line of code in mounted lifecycle hook which redirects to URL "not-found".
this.$router.replace({ path: 'not-found' });
But if URL is having parameters or query string it will append to it. For e.g- http://localhost:8080/home/not-found
What I want is that it only shows http://localhost:8080/not-found How should I achieve this. Please help. Thanks!
try this in your mounted function. worked on my side.
this.$router.push({path: '/not-found'})

Vue Js Axios get method

I use vue.js and I try to set a parameter id in axios.get request and I can't understand how exactly to do it
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import Movie from './views/Movie.vue'
Vue.use(Router)
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
},
{
path: '/movie/:m_id',
name: 'movie',
component: Movie
}
]
})
import Navbar from '../components/Navbar'
import axios from "axios"
export default {
components:{
Navbar
},
data () {
return {
movi: null,
}
},
mounted () {
axios
.get(`https://api.themoviedb.org/3/movie/${m_id}?api_key=7bc75e1ed95b84e912176b719cdeeff9&language=en-US`)
.then(response => (this.movi= response.data))
}
}
I am trying to pass to axios this id of the page to get information about that specific movie and I got stuck.
Any help?
You can try this to use your params from the URL:
// Retrieve the `m_id` param from the `this.$route.params` object:
this.$route.params.m_id
For more info see https://router.vuejs.org/api/#route-object-properties
#How can I do the same thing but in Vuex
import Vue from 'vue'
import Vuex from 'vuex'
import Axios from 'axios';
import router from './router'
Vue.use(Vuex)
Vue.use(Axios)
Vue.use(router)
export default new Vuex.Store({
// data() {
// return {
// m_id:this.$route.params.m_id
// }
// },
// m_id : this.$route.params.m_id,
state: {
video_key: [],
},
mutations: {
updateInfo (state , video_key){
state.video_key = video_key
}
},
getters:{
m_id : this.route.params.m_id
},
actions: {
fetchData({commit,getters}){
axios.get(`https://api.themoviedb.org/3/movie/${this.m_id}/videos?api_key=7bc75e1ed95b84e912176b719cdeeff9&language=en-US`)
.then(response =>{
commit('updateInfo',response.data.results[0].key)
})
}
}
})

Is there any way to load dynamic component in vuejs router..?

I'm working on a project there have a scope to use multiple themes/layouts based on certain condition. I've a dashboard panel there have 5 five pre-built themes and at a time admin can choose a certain theme and based on that section front-end view will be appear, suppose admin choose ThemeOne then the router will use only ThemeOne components,
route.js
const selectedTheme = 'themeTwo'
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/'+ selectedTheme + '/Home.vue'
import About from './views/'+ selectedTheme + '/About.vue'
Vue.use(Router)
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: About
}
]
})
Please help...Like this
You can do it by lazy load:
...
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: () => import('./views/'+ selectedTheme + '/Home.vue')
},
{
path: '/about',
name: 'about',
component: () => import('./views/'+ selectedTheme + '/About.vue')
}
]
})
Also you can use function to select component:
...
function setComponanet(componentName){
return () => import('./views/'+ selectedTheme +'/'+ componentName +'.vue')
}
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: setComponanet('Home'))
},
{
path: '/about',
name: 'about',
component: setComponanet('About')
}
]
})
If you dont want use dynamic path in import, you can use swtich in the function
function setComponanet(componentName){
if(selectedTheme == themeOne)
{
switch(componentName){
case 'Home': return () => import('./view/themeOne/Home');
case 'About': return () => import('./view/themeOne/About');
default: return () => import('./view/themeOne/NotFount');
}
}
else if(selectedTheme == themeTwo)
{
switch(componentName){
case 'Home': return () => import('./view/themeTwo/Home');
case 'About': return () => import('./view/themeTwo/About');
default: return () => import('./view/themeTwo/NotFount');
}
}
}
Another way with dynamic routes is using functional component
...
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/:theme/:compName',
name: 'theme',
component: Theme
props: (route)=>({ selectedComp: route.params.theme + route.params.compName }) //selectedComp: themeOneHome
}
]
})
// in Theme.vue
import themeOneHome from './themeOne/Home'
import theOneAbout from './themeOne/About'
import themeTwoHome from './themeTwo/Home'
import theTwoAbout from './themeTwo/About'
const components = {
themeOneHome,
themeOneAbout,
themeTwoHome,
theTwoAbout
}
export default {
functional: true,
props: ['selectedComp'],
render(h, ctx) {
return h(components[ctx.props.selectedComp], ctx.data, ctx.children)
}
}
You can load all your themes in your component and load a theme based on a variable.
Then, you can create any way to select your theme. For example, you can create a dropdown.
<template>
<component :is="themeSelector"></component>
</template>
<script>
import fooTheme from 'fooTheme'
import fooTheme2 from 'fooTheme2'
import fooTheme3 from 'fooTheme3'
export default {
name: 'fooParent',
components: {
fooTheme,
fooTheme2,
fooTheme3,
},
data: function() {
return {
themeSelector: 'fooTheme2'
}
}
}
</script>