mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
93 lines
3.3 KiB
TypeScript
93 lines
3.3 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*/
|
|
|
|
import {Attribute, ComponentFactory, ComponentFactoryResolver, ComponentRef, Directive, NoComponentFactoryError, ReflectiveInjector, ResolvedReflectiveProvider, ViewContainerRef} from '@angular/core';
|
|
|
|
import {RouterOutletMap} from '../router_outlet_map';
|
|
import {ActivatedRoute} from '../router_state';
|
|
import {PRIMARY_OUTLET} from '../shared';
|
|
|
|
/**
|
|
* A router outlet is a placeholder that Angular dynamically fills based on the application's route.
|
|
*
|
|
* ## Use
|
|
*
|
|
* ```
|
|
* <router-outlet></router-outlet>
|
|
* <router-outlet name="left"></router-outlet>
|
|
* <router-outlet name="right"></router-outlet>
|
|
* ```
|
|
*
|
|
* @stable
|
|
*/
|
|
@Directive({selector: 'router-outlet'})
|
|
export class RouterOutlet {
|
|
private activated: ComponentRef<any>;
|
|
private _activatedRoute: ActivatedRoute;
|
|
public outletMap: RouterOutletMap;
|
|
|
|
constructor(
|
|
parentOutletMap: RouterOutletMap, private location: ViewContainerRef,
|
|
private resolver: ComponentFactoryResolver, @Attribute('name') name: string) {
|
|
parentOutletMap.registerOutlet(name ? name : PRIMARY_OUTLET, this);
|
|
}
|
|
|
|
get isActivated(): boolean { return !!this.activated; }
|
|
get component(): Object {
|
|
if (!this.activated) throw new Error('Outlet is not activated');
|
|
return this.activated.instance;
|
|
}
|
|
get activatedRoute(): ActivatedRoute {
|
|
if (!this.activated) throw new Error('Outlet is not activated');
|
|
return this._activatedRoute;
|
|
}
|
|
|
|
deactivate(): void {
|
|
if (this.activated) {
|
|
this.activated.destroy();
|
|
this.activated = null;
|
|
}
|
|
}
|
|
|
|
activate(
|
|
activatedRoute: ActivatedRoute, loadedResolver: ComponentFactoryResolver,
|
|
providers: ResolvedReflectiveProvider[], outletMap: RouterOutletMap): void {
|
|
this.outletMap = outletMap;
|
|
this._activatedRoute = activatedRoute;
|
|
|
|
const snapshot = activatedRoute._futureSnapshot;
|
|
const component: any = <any>snapshot._routeConfig.component;
|
|
|
|
let factory: ComponentFactory<any>;
|
|
try {
|
|
if (typeof component === 'string') {
|
|
factory = snapshot._resolvedComponentFactory;
|
|
} else if (loadedResolver) {
|
|
factory = loadedResolver.resolveComponentFactory(component);
|
|
} else {
|
|
factory = this.resolver.resolveComponentFactory(component);
|
|
}
|
|
} catch (e) {
|
|
if (!(e instanceof NoComponentFactoryError)) throw e;
|
|
|
|
// TODO: vsavkin uncomment this once ComponentResolver is deprecated
|
|
// const componentName = component ? component.name : null;
|
|
// console.warn(
|
|
// `'${componentName}' not found in precompile array. To ensure all components referred
|
|
// to by the RouterConfig are compiled, you must add '${componentName}' to the
|
|
// 'precompile' array of your application component. This will be required in a future
|
|
// release of the router.`);
|
|
|
|
factory = snapshot._resolvedComponentFactory;
|
|
}
|
|
|
|
const inj = ReflectiveInjector.fromResolvedProviders(providers, this.location.parentInjector);
|
|
this.activated = this.location.createComponent(factory, this.location.length, inj, []);
|
|
this.activated.changeDetectorRef.detectChanges();
|
|
}
|
|
}
|