Angular 4 conditional routing/components

12,981

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';
    }
}
Share:
12,981
Out of Orbit
Author by

Out of Orbit

Updated on June 18, 2022

Comments

  • Out of Orbit
    Out of Orbit almost 2 years

    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>
    
  • Out of Orbit
    Out of Orbit almost 7 years
    I guess that would work but then I still have to manage a lot of "switching components logic" myself in the parent component. It would basically be the same as using *ngIf and add rules for which component to show and not.