Ответ 1
Angular 2 поддерживает ленивую загрузку на уровне модуля. Функциональные модули загружаются асинхронно, а не компонент. Вы можете создать этот компонентный модуль. https://angular.io/docs/ts/latest/guide/ngmodule.html
Я хочу привязать компонент к асинхронному маршруту, с условием.
Следующий пример, который работает (но является асинхронным), загружает один или несколько компонентов в зависимости от роли пользователя:
import { UserDashboardComponent } from './user-dashboard.component'
import { AdminDashboardComponent } from './admin-dashboard.component'
const role = 'admin' // Just for the example
const comp = role === 'admin' ? AdminDashboardComponent : UserDashboardComponent
const routes: Routes = [
{ path: '', component: comp },
]
Но, скажем, мы хотим получить роль из API, асинхронно. Каким образом это сделать?
Angular 2 поддерживает ленивую загрузку на уровне модуля. Функциональные модули загружаются асинхронно, а не компонент. Вы можете создать этот компонентный модуль. https://angular.io/docs/ts/latest/guide/ngmodule.html
Вы можете создать generic.module.ts, который будет иметь оба компонента в массиве объявлений:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UserDashboardComponent } from './user-dashboard.component'
import { AdminDashboardComponent } from './admin-dashboard.component
@NgModule({
imports: [ BrowserModule ],
declarations: [ UserDashboardComponent,AdminDashboardComponent ]
})
export class GenericModule { }
таким образом у вас будет модуль, содержащий модули, которые вы хотите загрузить.
Теперь следующий шаг - загрузить их асинхронно с помощью компилятора: внутри вашего компонента выполните следующие действия:
import {GenericModule} from './generic.module';
import { Component, Input,ViewContainerRef, Compiler, NgModule,ModuleWithComponentFactories,OnInit,ViewChild} from '@angular/core';
@Component({
selector: 'generic',
template: '<div #target></div>'
})
export class App implements AfterViewInit {
@ViewChild('target', {read: ViewContainerRef}) target: ViewContainerRef;
constructor(private compiler: Compiler) {}
ngAfterViewInit() {
this.createComponent('<u>Example template...</u>');
}
private createComponent(template: string,role:string) {
@Component({template: template});
const mod = this.compiler.compileModuleAndAllComponentsSync(GenericModule);
const factory = mod.componentFactories.find((comp) =>
//you can add your comparison condition here to load the component
//for eg. comp.selector===role where role='admin'
);
const component = this.target.createComponent(factory);
}
}
Надеюсь, что это поможет.
Вы можете просто определить компонент более высокого уровня f.e. DashboardComponent, который включен в маршрут/панели мониторинга
Затем родительский компонент должен загружать дочерние элементы в свой шаблон на основе асинхронного условия.
Таким образом вам также понадобится использовать * ngIf, но, по крайней мере, не загромождать шаблоны дочерних компонентов.
Поскольку вы будете использовать один маршрут для одного из компонентов, одно решение создает другой компонент для этого маршрута, тогда его шаблон может ссылаться на оба компонента, но с ngIf, как показано ниже:
<user-dashboard *ngIf="role==='user'"></user-dashboard>
<admin-dashboard *ngIf="role==='admin'"></admin-dashboard>
Я советую вам использовать навигацию по программному обеспечению с помощью метода навигации маршрутизатора. Таким образом, вы перечисляете все возможные маршруты в файле маршрутизатора. Затем в своем компоненте вы вызываете router.navigate() на основе конкретного случая.
Вы можете использовать Resolve
: https://angular.io/docs/ts/latest/api/router/index/Resolve-interface.html
Существует официальный пример, показывающий, как сделать перенаправление с Resolve
: https://angular.io/docs/ts/latest/guide/router.html#!#resolve-guard
Очень хорошим решением может быть "Use auth-guard". Вы можете попробовать реализовать интерфейсы CanActivate/CanLoad и поместить свое условие в этот класс.
Исходя из условия, маршруты активируются.
Пример:
import { Injectable } from '@angular/core';
import {
CanActivate,
ActivatedRouteSnapshot,
RouterStateSnapshot
} from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { Router } from '@angular/router';
@Injectable()
export class AuthorizationGuard implements CanActivate {
constructor() {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):
Observable<boolean> {
let url: string = state.url;
return this.canbeLoaded(url);
}
canbeLoaded(url: string): Observable<boolean> {
return Observable.of(true); //put your condition here
}
}