Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4 conditional routing/components

UPDATE: See below

So I have an app where I have two different organisations, when a user is using the app I therefore want to load different components depending on which organisation he belongs to.

Approach 1: Do a simple conditional in a routes file.

import { Routes } from '@angular/router';

import { UserStartComponent } from './user-start.component';
import { UserDetailComponent } from './user-detail/user-detail.component';

import { mia_UserStartComponent } from './mia/mia_user-start.component';
import { mia_UserDetailComponent } from './mia/user-detail/mia_user-detail.component';

const user = JSON.parse(localStorage.getItem('MYW_CLOUD_USER_INFO'));

const startcomp = user && user.custom_fields.organization && user.custom_fields.organization.name_id === 'mia' ? mia_UserStartComponent : UserStartComponent;
const detailcomp = user && user.custom_fields.organization && user.custom_fields.organization.name_id === 'mia' ? mia_UserDetailComponent : UserDetailComponent;


export const USERS_ROUTES: Routes = [
  { path: '', component: startcomp },
  { path: ':id', component: detailcomp }
];

This works, but ONLY on localhost, when I push to heroku and run in production the app just gives the wrong component. I've tried adding log outputs to this user-route.ts file, logs show up as expected on localhost but on production there is just nothing. "user" object from localStorage exist in both cases and are identical. NOTE: this approach was also working fine with Angular 2, with Angular 4 something seems to happen with the routes file when running in production but who knows what.. maybe its compiled in some way that make the if conditional break.

Approach 2. Use routes and guards. Add two guards for the different organisation. Works but the routes has to be different. The code below doesn't work as the first empty route is always checked, but the second is not. I need the path to be empty ('').

export const USERS_ROUTES: Routes = [
  { path: '', component: mia_UserStartComponent, canActivate: [OrganizationMiaGuard] },
  { path: '', component: UserStartComponent, canActivate: [OrganizationCelsiusGuard] }
  { path: ':id', component: detailcomp }
];

Since every topic on guards and conditional routing seems to be about whether to show "home" or "login" I don't really know if there is a better way to use guards. Ideally something like:

{ path: '', component: mia_UserStartComponent, canActivate: [OrganizationMiaGuard], **alternative**: UserStartComponent }

Approach 3. Use ngIf in parent template. This also works but I have to manually hide and show the component when moving further down the routes to "DetailsComponent"

SO how do you do something so seemingly trivial as showing a different component based on a conditional?

UPDATE 1:

The closest, although not working, I got to my desired behaviour was using named router outlets.

The right components are loaded but only for the two top routes. The ones with an empty path. For the the two routes with a id parameter I get

Error: Cannot match any routes. URL Segment: 'reports/1'

Which is weird because if I enter the url manually everything loads correctly:/ Called with:

<a [routerLink]="[userId]" ....

-

{ path: '', outlet: 'UserStartComponent', pathMatch: 'full', component: UserStartComponent },
{ path: '', outlet: 'mia_UserStartComponent', pathMatch: 'full', component: mia_UserStartComponent},

{ path: ':id', outlet: 'UserDetailComponent', pathMatch: 'full', component: UserDetailComponent },
{ path: ':id', outlet: 'mia_UserDetailComponent', pathMatch: 'full', component: mia_UserDetailComponent},

-

<router-outlet *ngIf="organization == 'celsius_golf'" name='UserStartComponent'></router-outlet>
<router-outlet *ngIf="organization == 'mia'" name='mia_UserStartComponent'></router-outlet>

<router-outlet *ngIf="organization == 'celsius_golf'" name='UserDetailComponent'></router-outlet>
<router-outlet *ngIf="organization == 'mia'" name='mia_UserDetailComponent'></router-outlet>
like image 285
Out of Orbit Avatar asked Jun 19 '17 13:06

Out of Orbit


1 Answers

Simply what about this?

routing config:

export const USERS_ROUTES: Routes = [
  { path: '', component: ToppageComponent },
  { path: ':id', component: detailcomp }
];

Toppage component:

@Component({
    template: `
        <mia-user-start *ngIf="mia"></mia-user-start>
        <user-start *ngIf="!mia"></user-start>
    `
})
export class ToppageComponent implements OnInit {

    mia: boolean;

    ngOnInit() {
        const user = JSON.parse(localStorage.getItem('MYW_CLOUD_USER_INFO'));
        this.mia = user && user.custom_fields.organization && user.custom_fields.organization.name_id === 'mia';
    }
}
like image 96
ttskch Avatar answered Oct 04 '22 21:10

ttskch