/** * @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 * * ``` * * * * ``` * * @stable */ @Directive({selector: 'router-outlet'}) export class RouterOutlet { private activated: ComponentRef; 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 = snapshot._routeConfig.component; let factory: ComponentFactory; 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(); } }