dynamic vue router - beforeEnter - infinite loop when using next() - javascript

I am trying to create a SPA which shows dealer in every state of austria. For example if a user visits example.com/vienna it shows every dealer in vienna. But if a users visits example.com/paris, he will still get directed to the dynamic route /paris but of course there will be nothing shown.
So my approach was to check if the state which the user wants to search for is available in the list of state and therefore directing it to the available state or redirect him to a 404 page.
If the state is available it works, but if I'll try to go to a non existing state I am stuck in a loop from next('/404')
export default new Router({
routes: [{
path: '/',
name: 'Home',
component: Home
},{
path: '/:region',
component: RegionQuery,
beforeEnter: (to, from, next) => {
let isRegion = false;
let allRegions = storeConfig.state.states;
let toRegion = to.params.region;
for(var i in allRegions){
if(allRegions[i].route === toRegion){
isRegion = true;
}
}
if (isRegion) {
next();
} else {
next('/404');
}
}
},
{
path: '/404',
name: '404',
component: NotFound
},
{
path: '*',
redirect: '/404'
},
],
})
What am I doing wrong or is there a better approach to my problem?

/404 is matched to /:region
You need to change your path order
export default new Router({
routes: [{
path: '/',
name: 'Home',
component: Home
},
{
path: '/404',
name: '404',
component: NotFound
},{
path: '/:region',
component: RegionQuery,
beforeEnter: (to, from, next) => {
let isRegion = false;
let allRegions = storeConfig.state.states;
let toRegion = to.params.region;
for(var i in allRegions){
if(allRegions[i].route === toRegion){
isRegion = true;
}
}
if (isRegion) {
next();
} else {
next('/404');
}
}
},
{
path: '*',
redirect: '/404'
},
]

Related

Angular Route Custom Fallback Logic

I have a standard set of Routes:
export const ROUTES: Routes = [
{
path: '', redirectTo: 'home'
},
{
path: 'notentitled', component: 'NotEntitledComponent'
},
{
path: 'welcome', component: 'WelcomeComponent', canActivate: [RoutingService]
},
{
path: 'active', component: 'ActiveComponent', canActivate: [RoutingService]
},
{
path: 'table', component: 'TableComponent', canActivate: [RoutingService]
},
{
path: '**', component : NotFoundComponent
}
];
The canActivate method pulls in the users entitlement credentials and checks the target route ie 'active' against their entitlement ie:
public canActivate(route: ActivateRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
let target = state.url;
return entitlementService.getUserInfo()
.pipe(
map(data => {
let canSeePage = data?.entitlements?['target'];
return canSeePage;
}),
catchError((error: any) => {
route.navigate(['notentitled']);
return of(false);
});
}
I want to add some logic to cater to a scenario. If in the entitlement check ie:
let canSeePage = data?.entitlements?['target'];
false; before returning false; check if user can see any other page and redirect there.
Example, user requests 'active' route, however, this fails:
let canSeePage = data?.entitlements?['target']; // ie data.entitlements.active: false
However, data.entitlements.table is true, so redirect to 'table'

Vue JS Router Guard

I am learning Vue JS and so far so good. I have an API which I am using for my backend and on successful login, it is giving me access and a refresh token. In Vue, I am checking localStorage for the token and if null I need to redirect to the login page. If present I need to make an API call to check if valid and redirect to log in or the intended route depending on the response. So far the code below is what I have managed to put up but is saying Detected an infinite redirection in a navigation guard when going from "/" to "/". Aborting to avoid a Stack Overflow. This will break in production if not fixed
Here is may code
router.beforeEach((to, from, next ) =>{
console.log(to.meta)
let tokens = JSON.parse(localStorage.getItem('chikolo_tokens'))
if (tokens!== null && to.meta.requiresAuth) {
next()
}
else{
next({ name: 'login' })
}
})
Routes
{
path: '/',
name: 'login',
component: Login,
meta: { requiresAuth: false },
},
{
path: '/admin/home/',
name: 'home',
component: AdminHome,
meta: { requiresAuth: true },
},
{
path: '/admin/users/',
name: 'adminUsers',
component: Users,
meta: { requiresAuth: true },
},
How do I navigate to the login page if tokens is null?
tokens!== null && to.meta.requiresAuth is always false for / route.
A redirect should happen only for routes that require auth:
if (to.meta.requiresAuth && !tokens) {
next({ name: 'login' })
} else{
next()
}
Kindly try this
const routes = [
/** admin*/
{
path: '/admin/home',
name:'adminHome',
component: homeAdminIndex,
meta:{
requiresAuth :true
}
},
/** pages*/
{
path: '/',
name:'Home',
component: homePageIndex,
meta:{
requiresAuth :false
}
},
router.beforeEach((to,from) =>{
if (to.meta.requiresAuth && !localStorage.getItem('token')){
return { name: 'Login'}
}
if (to.meta.requiresAuth == false && localStorage.getItem('token')){
return { name: 'adminHome'}
}
})

How to Set ? in routeFile in Angular

My Requirement is From Backend I am getting routes as "app/dashboard?dashboard_id={id}"
How can I configure this in Module.ts file?
I tried using below
const routes: Routes = [
{
path: "app/dashboard/:dashboard_id",
component: AddEditComponent,
canActivate: [AuthGuard],
},
];
but I am getting errors like routes are not defined.
Can Someone Please Help me on that how can I configure this route as I need to catch this id as queryParams in Component.
You can do something like this:
const routes: Routes = [
{
path: "app/dashboard",
component: AddEditComponent,
canActivate: [AuthGuard],
children: [
{
path: ':dashboard_id'
component: NewComponentId
}
]
},
];
and in your NewComponentId you can do something like inside the constructor to catch the id:
this.route.paramMap.pipe(
map((paramMap) => {
if (paramMap.get('id') !== 'something') {
// your code
}
}),
Required Route param:
{path: 'users/:userId', component: UserComponent}
and get it from param:
constructor(params: RouteParams) {
var paramId = params.get("id");
}
Optional Route Param:
{ path: '/user', component: UserComponent }
its just define the route part and param pass by query string, to read the queryparam:
this.route.queryParams
.subscribe(params => {
console.log(params);
}
);
you must process the query string for this route: "app/dashboard?dashboard_id={id}"
Update:
To set the queryparam in routerlink use it this way:
<a routerLink="/dashboard" [queryParams]="{ dashboard_id: 11 }"
>another dashboard</a>

Vue / Vue-bulma - nprogress: Progress bar loads forever on guard/redirect

nprogress works just fine in every other regard, but on redirect to /login it spins forever. I've attempted the showProgressBar: false to no avail.
If user is logged in they'll be redirected to /dashboard, if they are not they will be redirected to /login.
My code looks like this:
const routes = [
{path: '/', name: 'root', redirect: { name: 'login' }, meta: {showProgressBar: false}},
{path: '/login', component: LoginPage, name: 'login', beforeEnter: loggedIn, meta: {showProgressBar: false}},
{path: '/dashboard', component: DashboardPage, name: 'dashboard', meta: { requiresAuth: true }},
{path: '/editor', component: PhoneEditorPage, name: 'editor', meta: { requiresAuth: true }},
{path: '/usersettings', component: PinPasswordPage, name: 'pinpassword', meta: { requiresAuth: true }},
{path: '/callforwarding', component: CallForwardingPage, name: 'callforwarding', meta: { requiresAuth: true }},
{ name: 'dropdown', path: '/dropdown', component: Dropdown, meta: { requiresAuth: true }}
]
const router = new VueRouter({
linkActiveClass: 'active',
mode: 'hash',
routes
})
function loggedIn (to, from, next) {
const authUser = JSON.parse(window.localStorage.getItem('authUser'))
if (authUser && authUser.auth) {
next({name: 'dashboard'})
} else {
next()
}
}
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth) {
const authUser = JSON.parse(window.localStorage.getItem('authUser'))
if (authUser && authUser.auth) {
next()
} else {
next({name: 'login'})
this.nprogress.done()
}
}
next()
Thank you for your time.
Isn't simple to answer without see code in action, but, you can try to invert call to this.nprogess.done() and next(...) like this:
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth) {
const authUser = JSON.parse(window.localStorage.getItem('authUser'))
if (authUser && authUser.auth) {
next()
} else {
this.nprogress.done(); // <- HERE
next({name: 'login'})
}
}
next()
}
since next() call move context to new component, and I'm not sure call to nprogress will be called on the right moment.

vue,js vue-router 2 component data doesn't update

I'm fairly new to vue.js and trying to build an SPA. Basicly i define all routes from my backend with an alias to my API endpoints. a lot of them using the same component. Data gets fetched with router.beforeEach and vue-resource.
Now when i navigate from a route to another route which share the same template, my router-view doens't get updated.
Here's my code:
<script>
var data = {
content: null
}
const site = {
template:'<div>{{this.title}}</div>',
data: function () {
return data.content.body
}
}
const home = {
template:'<div>{{this.title}}</div>',
data: function () {
return data.content.body
}
}
const routes = [
{ path: '/api/12.json', component: home, alias: '/' },
{ path: '/api/4.json', component: site, alias: '/projekte' },
{ path: '/api/5.json', component: site, alias: '/projekte/projekt-1' },
{ path: '/api/7.json', component: site, alias: '/projekte/projekt-2' },
{ path: '/api/6.json', component: site, alias: '/projekte/projekt-3' },
{ path: '/api/8.json', component: site, alias: '/agentur' },
{ path: '/api/9.json', component: site, alias: '/lab' },
{ path: '/api/10.json', component: site, alias: '/kontakt' },
]
const router = new VueRouter({
routes
})
router.beforeEach((to, from, next) => {
Vue.http.get(to.matched[0].path).then((response) => {
data.content = response;
console.log(data.content);
next();
}, (response) => {
data.content = {
'body': {
'title': 'Error 404'
}
};
next();
});
})
const app = new Vue({
router
}).$mount('#app')
</script>
Your data object is not part of your Vue component. It is defined outside of your Vue app.
Even though your components - home and site returns the data.content.body object, your main data object is not part of Vue's reactivity system. Therefore, the changes in that data object are not tracked.
You can read more about it here: https://vuejs.org/guide/reactivity.html
To ensure that this does not happen, you need to define your data as part of your component itself. And you need to do your http calls as part of mounted hook on the route component, which has access to this.data of the component.
If you need to share data between components (most likely), then you need to use state management using vuex that allows you to have a shared state for the entire Vue app.
You can read more about Vuex here: http://vuex.vuejs.org/en/intro.html
Here's a working example of vue / vue-router / vuex / vue-resource example for API Calls. Thanks at Mani for the hint i needed.
const site = {
template:'<div>{{ content.title }}</div>',
computed: {
content (){
return store.state.routeContent
}
}
}
const home = {
template:'<div>{{ content.title }}</div>',
computed: {
content (){
return store.state.routeContent
}
}
}
const notFound = {
template: '<div>{{ content.title }}</div>',
computed: {
content (){
return store.state.routeContent
}
}
}
const routes = [
{ path: '/api/12.json', component: home, alias: '/' },
{ path: '/api/4.json', component: site, alias: '/projekte' },
{ path: '/api/5.json', component: site, alias: '/projekte/projekt-1' },
{ path: '/api/7.json', component: site, alias: '/projekte/projekt-2' },
{ path: '/api/6.json', component: site, alias: '/projekte/projekt-3' },
{ path: '/api/8.json', component: site, alias: '/agentur' },
{ path: '/api/9.json', component: site, alias: '/lab' },
{ path: '/api/10.json', component: site, alias: '/kontakt' },
{ path: '/*', component: notFound }
]
const store = new Vuex.Store({
state: {
routeContent: null
},
mutations: {
routeContent (state, payload) {
state.routeContent = payload
document.title = payload.title
}
}
})
const router = new VueRouter({
routes
})
router.beforeEach((to, from, next) => {
Vue.http.get(to.matched[0].path).then((response) => {
store.commit('routeContent', response.body)
next()
}, (response) => {
console.log(response);
errorObject = {
'title': 'Error 404'
},
store.commit('routeContent', errorObject)
next()
});
})
const app = new Vue({
router
}).$mount('#app')

Categories