Vue router doesn't recognize :lang as a param - javascript

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}
},
]
})

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: ...
},
...
]

vue-router 4 '/:pathMatch(.*)*' not working?

hello guys I want to ask about vue-router.
when I use vue 2 if there is a page that doesn't match, I use path: '*' to go to my page404 but in vue 3 it's been replaced with '/:pathMatch(.)' after i tried it the warning in console disappeared but i just got a blank page and it doesn't point to my page404. did i miss something? I'm newbie with vue 3
here is the version I'm using:
vue: ^3.0.0
vue-router: ^4.0.0-0
and this is my index.js
import { createRouter, createWebHistory, RouterView } from 'vue-router'
const routes = [
{
path: '/',
redirect: '/login',
component: RouterView,
children: [{
path: '/login',
component: () => import('#/views/login/Login.vue'),
}]
},
{
path: '/:pathMatch(.*)*',
component: () => import('#/views/page404/Page404.vue')
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
You can try to write it like this
{
path: "/:pathMatch(.*)*",
redirect: "/404"
},
{
path: "/404",
name: "404",
component: () => import("#/views/page404/Page404.vue")
}

Vue route only works after visiting root URL first

I'm using Vue Router to redirect https://example.com/foo to https://example.com/foo/randomID.
This only works if the root URL https://example.com are visited first - otherwise a direct call of https://example.com/foo results in a 404 not found.
I can't figure out the root cause of this.
What I've tried so far:
New build
Update NPM packages
Clean install on server
Clean Site Data via Chrome Dev Tools
router.js:
import Vue from 'vue'
import Router from 'vue-router'
import Head from 'vue-head'
import Home from '#/views/Home'
import CheckLogin from '#/views/CheckLogin'
import { isNil } from 'lodash'
import store from '#/store'
Vue.use(Router)
/* If you don't know about VueHead, please refer to https://github.com/ktquez/vue-head */
Vue.use(Head, {
complement: process.env.VUE_APP_TITLE
})
/* If you don't know about VueRouter, please refer to https://router.vuejs.org/ */
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/home',
name: 'home',
component: Home,
meta: {
authNotRequired: true
}
},
{
path: '/check-login',
name: 'check-login',
component: CheckLogin,
meta: {
authNotRequired: true
}
},
{
path: '/login',
name: 'login',
component: () =>
import(
/* webpackChunkName: "client-chunk-login" */ '#/views/Login.vue'
),
meta: {
authNotRequired: true
}
},
{
path: '/products',
name: 'products',
component: () =>
import(
/* webpackChunkName: "client-chunk-products" */ '#/views/Products.vue'
)
},
{
path: '/item/:id',
name: 'item',
props: true,
component: () =>
import(
/* webpackChunkName: "client-chunk-product-details" */ '#/views/Item.vue'
)
},
{
path: '/list/:id',
name: 'list',
props: true,
component: () =>
import(
/* webpackChunkName: "client-chunk-product-details" */ '#/views/List.vue'
),
meta: {
authNotRequired: true
}
},
{
path: '/list',
name: 'listredirect',
props: true,
component: () =>
import(
/* webpackChunkName: "client-chunk-product-details" */ '#/views/Listredirect.vue'
),
meta: {
authNotRequired: true
}
},
{ path: '*', redirect: '/home' }
]
})
/**
* Handle user redirections
*/
// eslint-disable-next-line consistent-return
router.beforeEach((to, from, next) => {
if (
!(to.meta && to.meta.authNotRequired) &&
isNil(store.state.authentication.user)
) {
const path =
store.state.authentication.user === null ? '/login' : '/check-login'
return next(`${path}?redirectUrl=${to.path}`)
}
next()
})
export default router
The vue.config.production.js:
const path = require('path')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer') // eslint-disable-line
.BundleAnalyzerPlugin
const PrerenderSPAPlugin = require('prerender-spa-plugin') // eslint-disable-line
const prerenderedRoutesList = ['/login', '/home', '/']
// TODO stats raus aus dist -> plugin ganz raus?!
module.exports = {
configureWebpack: {
plugins: [
/* Refer to https://www.npmjs.com/package/webpack-bundle-analyzer for more details */
new BundleAnalyzerPlugin({
analyzerMode: 'disabled',
generateStatsFile: true
}),
/* See https://github.com/chrisvfritz/prerender-spa-plugin for more details */
new PrerenderSPAPlugin({
// Required - The path to the webpack-outputted app to prerender.
staticDir: path.join(__rootDirname),
// Required - Routes to prerender.
routes: prerenderedRoutesList
})
]
}
}
The redirect component:
<template>
<div>
{{ this.$router.push('/list/new') }}
</div>
</template>
Any ideas on how to fix this issue are appreciated.
Maybe you could use Vue Router redirect function? Eg.
routes: [
{ path: '/foo', redirect: to => {
// code you need...
return "/foo/id";
}}
]
basically you need to redirect your 404 hits to index.html, then the path will resolve correctly. Read here for more information
You can use redirect in the vue-router
routes: [
{ path: '/foo', redirect: '/foo/:randomId' }
]
this.$route.params.randomId will be in the component.
Have a look at docs here

VueJS | How can i get url parameters in vue.js?

Hi I'm making my own websites. and i'm newbie vue.js
I'm trying to get parameters to url.
I've been trying to any method. but not works.
Here is a url. -> example.com:8080/login
in this page, there's a button to register.
All i want is when i give url parameter(example.com:8080/login?id=hello&pw=1234), in login.vue, insert value -> user_id = hello, user_pw = 1234 and going back to exapmle.com:/8080
i'm trying to using vue.router. but it not works.
the error is
javax.servlet.ServletException: Circular view path [error]: would dispatch back to the current handler URL [/error] again. Check your ViewResolver setup!
and this is /router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Main from '../views/Main.vue'
import Login from '../views/Login.vue'
import Intro from '../views/Intro.vue'
import Info from '../views/Info.vue'
import Setting from '../views/Setting.vue'
import store from '../store'
import user_id from '../views/Login.vue'
import user_pw from '../views/Login.vue'
Vue.use(VueRouter)
const routes = [{
path: '/',
redirect: '/main',
},
{
path: '/login',
name: 'login',
component: Login,
},
{
path: '/signup',
name: '/signup',
component: SignUp
},
{
path: '/main',
component: Main,
beforeEnter(to, from, next) {
if (store.state.accessToken) {
next();
} else {
next('/login');
}
},
children: [{
path: '',
name: 'intro',
component: Intro,
},
{
path: '/info',
name: 'info',
component: Info,
},
{
path: '/setting',
name: 'setting',
component: Setting,
},
]
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes: Login
});
var myApp = new Vue({
router,
el: '#app',
mounted: function() {
let parameters;
parameters = this.$route.query
console.log(parameters)
user_id = this.$route.query.id
user_pw = this.$route.query.pw
}
})
export default router
and this is part of login.vue
export default {
name: "test",
function() {
return {
id: "",
pw: "",
};
},
methods: {
test() {
axios.post("/login", {
id: this.userId,
pw: this.password
})
.then(function(response) {
if(response.data.code === 200) {
}
})
},
mounted : function() {
this.load();
}
}
i don't know what is wrong in my code.
my explain is too bad. sorry. but i'm trying to do my best
You are assigning routes to the Login component.
Replace
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes: Login
});
with
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
});
"Hello world" example (Maybe it will be helpful). Click on the link to get utm_source:
const User = {
template: `<div><b>User:</b> {{ this.$route.params.id }} | <b>utm_source:</b>
{{this.$router.currentRoute.query['utm_source']}}</div>`
}
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User }
]
})
const app = new Vue({ router }).$mount('#app')
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<nav>
<router-link to="/user/foo?utm_source=facebook">Click her to see the utm_source=facebook of /user/foo?utm_source=facebook</router-link>
</nav>
<router-view></router-view>
</div>

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');
}
});

Categories

Resources