/** * @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, EventEmitter, Injector, OnDestroy, Output, ReflectiveInjector, ResolvedReflectiveProvider, ViewContainerRef} from '@angular/core'; import {RouterOutletMap} from '../router_outlet_map'; import {ActivatedRoute} from '../router_state'; import {PRIMARY_OUTLET} from '../shared'; /** * @whatItDoes Acts as a placeholder that Angular dynamically fills based on the current router * state. * * @howToUse * * ``` * * * * ``` * * A router outlet will emit an activate event any time a new component is being instantiated, * and a deactivate event when it is being destroyed. * * ``` * * ``` * @selector 'a[routerLink]' * @ngModule RouterModule * * @stable */ @Directive({selector: 'router-outlet'}) export class RouterOutlet implements OnDestroy { private activated: ComponentRef; private _activatedRoute: ActivatedRoute; public outletMap: RouterOutletMap; @Output('activate') activateEvents = new EventEmitter(); @Output('deactivate') deactivateEvents = new EventEmitter(); constructor( private parentOutletMap: RouterOutletMap, private location: ViewContainerRef, private resolver: ComponentFactoryResolver, @Attribute('name') private name: string) { parentOutletMap.registerOutlet(name ? name : PRIMARY_OUTLET, this); } ngOnDestroy(): void { this.parentOutletMap.removeOutlet(this.name ? this.name : PRIMARY_OUTLET); } 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) { const c = this.component; this.activated.destroy(); this.activated = null; this.deactivateEvents.emit(c); } } activate( activatedRoute: ActivatedRoute, loadedResolver: ComponentFactoryResolver, loadedInjector: Injector, providers: ResolvedReflectiveProvider[], outletMap: RouterOutletMap): void { this.outletMap = outletMap; this._activatedRoute = activatedRoute; const snapshot = activatedRoute._futureSnapshot; const component: any = snapshot._routeConfig.component; let factory: ComponentFactory; if (loadedResolver) { factory = loadedResolver.resolveComponentFactory(component); } else { factory = this.resolver.resolveComponentFactory(component); } const injector = loadedInjector ? loadedInjector : this.location.parentInjector; const inj = ReflectiveInjector.fromResolvedProviders(providers, injector); this.activated = this.location.createComponent(factory, this.location.length, inj, []); this.activated.changeDetectorRef.detectChanges(); this.activateEvents.emit(this.activated.instance); } }