Vuejs fill <component> with dynamic params in url - javascript

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>

Related

Defining routes in a separate file and using them inside index.js

I have this routes inside my index.js
import {
createRouter,
createWebHistory
}
from '#ionic/vue-router';
import {
RouteRecordRaw
}
from 'vue-router';
const routes = [{
path: '',
redirect: '/tabs'
}, {
path: '/tabs',
component: () => import('../views/tabs/TabRoot.vue'),
children: [{
path: '',
redirect: '/tabs/home'
}, {
path: '/tabs/home',
component: () => import('../views/tabs/Home.vue')
},
]
},
//Sell
{
path: '/sell',
component: () => import('../views/pages/sell/Sell.vue')
},
//Categories
{
path: '/trending',
component: () => import('../views/pages/Trending.vue')
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router
and i would like to define the follwoing routes isnide others.js file and have this inside
{
path: '/crud_ui_landing_vehicles',
component: () => import('../views/pages/sell/categories/Vehicles.vue')
},
{
path: '/crud_ui_landing_properties',
component: () => import('../views/pages/sell/categories/Properties.vue')
},
The imported routes should be used inside const routes array object.
How can i define and import the routes file?
Using the spread operator
// others.js
export const others = [...]
import { others } from './others.js'
const routes = [
...others,
👆
{
path: ...,
component: ...
},
...
]

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

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.

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.

Vue / vue-router scoping

import ExpenseView from './path'
import template from './path'
const MainComponent = new Vue({
el: '#app',
data: {
expense: [{ description: 'expense description', amount: 14.99, _id: 'l;dkfjg;ladfjg;klafjg;l' }],
},
router: new VueRouter({
routes: [
{ path: '/dash', component: ExpenseView, props: { default: true, expenses: MainComponent.expense } },
]
}),
template,
created() {...},
methods: {...},
computed: {...}
})
My goal is to have the router listen to the data in MainComponent but there are scoping issues - MainComponent is not defined.
Is there a way to get the router listening to the data in MainComponent with the way this is structured?
You can see the following example
//you can try the following code
//index.js
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
import RSSFeed from '#/components/RSSFeed.vue'
export default new Router({
routes: [
{
path: '/rss-feed',
name: 'RSSFeed',
component: RSSFeed,
props: { authorName: 'Robert' }
},
]
})
//RSSFeed.vue
<template>
<ol id="feed">
{{authorName}}
</ol>
</template>
<script>
import Post from './Post'
export default {
props: ['authorName'],
data () {
return {
items: [
{
"title":"Vuejs Nodejs",
"pubDate":"20-07-2018",
"description":"Leading vuejs nodejs",
"link":"https://hoanguyenit.com"
}
],
errors: []
}
}
}
</script>
Example
//in router
const router = new VueRouter({
routes: [
{ path: 'YOUR__PATH', component: Home, props: { authorName: 'Robert' } }
]
})
//in Home.vue
//And inside the <Home /> component,
var Home = Vue.extend({
props: ['authorName'],
template: '<p>Hey, {{ authorName }}</p>'
});

Vue.js 2 router only loading component from navigation and not from URL

When clicking to view page content from the menu the correct component loads. However, when I go it directly from the URL it doesn't.
This is the master page (which loads the menu):
<template>
<div class="row">
<div class="col-md-3 col-sm-3 col-xs-3">
<router-link to="/new-page" type="button" class="btn btn-primary btn-lg btn-block">New page</router-link>
<div class="list-group sidebar">
<router-link v-for="page in pages" class="list-group-item" :to="'/pages/' + page.slug">{{ page.menu_title }}</router-link>
</div>
</div>
<div class="col-md-9 col-sm-9 col-xs-9">
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
computed: {
pages() {
return this.$store.state.pages
}
},
created() {
this.$http.get('pages').then((response) => {
this.$store.commit('setPages', response.body)
console.log(response)
}, (response) => {
console.log("Error: " + response)
})
}
}
</script>
This is the content which loads a content type depending what page type is clicked. You can use multiple templates which reloads with different data (that part is OK)
<template>
<div>
<div class="loader" v-if="loading">
<div class="bounce1"></div>
<div class="bounce2"></div>
<div class="bounce3"></div>
</div>
<div v-if="!loading">
<vc-gig :content="content" v-if="content.type == 'gig'"></vc-gig>
<vc-news :content="content" v-if="content.type == 'news'"></vc-news>
<vc-home :content="content" v-if="content.type == 'home'"></vc-home>
<vc-image :content="content" v-if="content.type == 'image'"></vc-image>
</div>
</div>
</template>
<script>
import Gig from '../Gig.vue'
import News from '../News.vue'
import Home from '../Home.vue'
export default {
components: {
'vc-gig': Gig,
'vc-news': News,
'vc-home': Home,
},
data() {
return {
loading: true,
content: [],
}
},
created() {
this.getPageData
},
watch: {
'$route': 'getPageData'
},
methods: {
getPageData() {
this.loading = true
this.$http.get('pages/' + this.$route.params.pageSlug).then((response) => {
this.content = response.body
this.loading = false
console.log(response.body)
}, (response) => {
console.log(response)
})
}
}
}
</script>
All components load correctly when clicking the menu (in the first code section) but if I add the URL manually in the browser the page content (second code section) wont load.
Update: Here is my full routes.js file:
import Vue from 'vue'
import VueRouter from 'vue-router'
// Public
import Home from './views/Pages/Home.vue'
// Authentication
import Login from './views/Auth/Login.vue'
import Register from './views/Auth/Register.vue'
import Onboarding from './views/Auth/Onboarding.vue'
import ResetPassword from './views/Auth/ResetPassword.vue'
// Pages & Items
import Pages from './views/Pages/Layout/PageMaster.vue'
import Page from './views/Pages/Layout/PageSinge.vue'
import Item from './views/Pages/Layout/PageItem.vue'
import NewPage from './views/Pages/NewPage.vue'
// Options
import Options from './views/Options/Layout/OptionsMaster.vue'
import Themes from './views/Options/Themes.vue'
import Logo from './views/Options/Logo.vue'
import SocialMediaIcons from './views/Options/SocialMediaIcons.vue'
import WebsiteTitle from './views/Options/WebsiteTitle.vue'
import DomainName from './views/Options/DomainName.vue'
import Meta from './views/Options/Meta.vue'
import AnalyticsWebtools from './views/Options/AnalyticsWebtools.vue'
// My Account
import Account from './views/Account/Layout/AccountMaster.vue'
import Billing from './views/Account/Billing.vue'
import Details from './views/Account/Details.vue'
import Password from './views/Account/Password.vue'
Vue.use(VueRouter)
const Router = new VueRouter({
mode: 'history',
routes: [
{
path: '/login',
name: 'login',
component: Login,
meta: {guest: true}
},
{
path: '/register',
name: 'register',
component: Register,
meta: {guest: true}
},
{
path: '/reset-password',
name: 'reset-password',
component: ResetPassword,
meta: {guest: true}
},
{
path: '/onboarding',
name: 'onboarding',
component: Onboarding
},
{
path: '/',
name: 'home',
redirect: 'pages/home',
component: Home,
meta: {auth: true}
},
{
path: '/new-page',
name: 'newpage',
component: NewPage,
meta: {auth: true}
},
{
path: '/pages',
name: 'pages',
redirect: 'pages/home',
component: Pages,
meta: {auth: true},
children: [
{
path: ':pageSlug',
name: 'page',
component: Page,
},
]
},
{
path: '/pages/:pageSlug/:itemSlug',
name: 'item',
component: Item,
meta: {auth: true}
},
{
path: '/options',
name: 'options',
redirect: 'options/themes',
component: Options,
meta: {auth: true},
children: [
{
path: 'themes',
name: 'themes',
component: Themes
},
{
path: 'logo',
name: 'logo',
component: Logo
},
{
path: 'social-media-icons',
name: 'socialmediaicons',
component: SocialMediaIcons
},
{
path: 'website-title',
name: 'sitetitle',
component: WebsiteTitle
},
{
path: 'domain-name',
name: 'domain',
component: DomainName
},
{
path: 'meta-text-image',
name: 'meta',
component: Meta
},
{
path: 'analytics-webtools',
name: 'tools',
component: AnalyticsWebtools
},
]
},
{
path: '/account',
name: 'account',
component: Account,
meta: {auth: true},
children: [
{
path: 'billing',
name: 'billing',
component: Billing
},
{
path: 'details',
name: 'details',
component: Details
},
{
path: 'password',
name: 'password',
component: Password
},
]
}
]
})
Router.beforeEach(function (to, from, next) {
// User is authenticated
if (to.matched.some(function (record) {
return record.meta.guest
}) && Vue.auth.loggedIn()) {
next({
path: '/pages'
})
} else {
next()
}
// User not authenticated
if (to.matched.some(function (record) {
return record.meta.auth
}) && !Vue.auth.loggedIn()) {
next({
path: '/login'
})
} else {
next()
}
})
export default Router
Simple fix, you are not calling the method you created.
created() {
this.getPageData
},
should be
created() {
this.getPageData()
},
Also perhaps using a linter such as eslint would help avoid these mistakes.
http://eslint.org/
Happy coding!

Categories

Resources