Angular 4 conditional routing/components
Asked Answered
V

2

6

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>
Virulence answered 19/6, 2017 at 13:26 Comment(5)
how do you determine the user is from which org , i guess from some url path params or query params . you can extract this value on component load and then load or reroute the app to load components , you could also look into dynamic components but i donot think it meant for such trivial thing. Make sure to change the base href when you deploy to the serverExploit
I get the user info from localStorage. Maybe Im just better of making different routes for different organisations, but it seems odd that such a thing should be necessaryVirulence
so you can get value from the local storage in your service and then call the appropriate route from that value is that not working ?Exploit
Yes I could do that, but up until now I haven't had separate routes. It has been the same route but in my routes file I have assigned different components based on conditional. Which worked fine in Angular 2 but not in Angular 4. Maybe its the wrong approach:/Virulence
yes I also need solution to this, in my case I want to handle dynamic subdomainPenza
P
1

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';
    }
}
Pyroelectric answered 21/6, 2018 at 15:16 Comment(0)
S
0

You could try the dynamic component loader.

Details are in the Angular docs here: https://angular.io/guide/dynamic-component-loader

Supplemental answered 19/6, 2017 at 17:25 Comment(1)
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.Virulence

© 2022 - 2024 — McMap. All rights reserved.