diff --git a/modules/@angular/router/src/directives/router_outlet.ts b/modules/@angular/router/src/directives/router_outlet.ts
index 4d65a7dcab..26729fa677 100644
--- a/modules/@angular/router/src/directives/router_outlet.ts
+++ b/modules/@angular/router/src/directives/router_outlet.ts
@@ -6,16 +6,17 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {Attribute, ComponentFactory, ComponentFactoryResolver, ComponentRef, Directive, NoComponentFactoryError, ReflectiveInjector, ResolvedReflectiveProvider, ViewContainerRef} from '@angular/core';
+import {Attribute, ComponentFactory, ComponentFactoryResolver, ComponentRef, Directive, EventEmitter, NoComponentFactoryError, Output, 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
+ * ## Example
*
* ```
*
@@ -23,6 +24,16 @@ import {PRIMARY_OUTLET} from '../shared';
*
* ```
*
+ * 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.
+ *
+ * ## Example
+ *
+ * ```
+ *
+ * ```
+ *
* @stable
*/
@Directive({selector: 'router-outlet'})
@@ -31,6 +42,9 @@ export class RouterOutlet {
private _activatedRoute: ActivatedRoute;
public outletMap: RouterOutletMap;
+ @Output('activate') activateEvents = new EventEmitter();
+ @Output('deactivate') deactivateEvents = new EventEmitter();
+
constructor(
parentOutletMap: RouterOutletMap, private location: ViewContainerRef,
private resolver: ComponentFactoryResolver, @Attribute('name') name: string) {
@@ -49,8 +63,10 @@ export class RouterOutlet {
deactivate(): void {
if (this.activated) {
+ const c = this.component;
this.activated.destroy();
this.activated = null;
+ this.deactivateEvents.emit(c);
}
}
@@ -86,5 +102,7 @@ export class RouterOutlet {
const inj = ReflectiveInjector.fromResolvedProviders(providers, this.location.parentInjector);
this.activated = this.location.createComponent(factory, this.location.length, inj, []);
this.activated.changeDetectorRef.detectChanges();
+
+ this.activateEvents.emit(this.activated.instance);
}
}
diff --git a/modules/@angular/router/test/router.spec.ts b/modules/@angular/router/test/router.spec.ts
index f6a43166ed..991030c4ff 100644
--- a/modules/@angular/router/test/router.spec.ts
+++ b/modules/@angular/router/test/router.spec.ts
@@ -415,6 +415,48 @@ describe('Integration', () => {
.toHaveText('primary {simple} right {user victor}');
})));
+ it('should emit an event when an outlet gets activated',
+ fakeAsync(inject(
+ [Router, TestComponentBuilder, Location],
+ (router: Router, tcb: TestComponentBuilder, location: Location) => {
+ @Component({
+ selector: 'container',
+ template:
+ ``
+ })
+ class Container {
+ activations: any[] = [];
+ deactivations: any[] = [];
+
+ recordActivate(component: any): void { this.activations.push(component); }
+
+ recordDeactivate(component: any): void { this.deactivations.push(component); }
+ }
+
+ const fixture = createRoot(tcb, router, Container);
+ const cmp = fixture.debugElement.componentInstance;
+
+ router.resetConfig(
+ [{path: 'blank', component: BlankCmp}, {path: 'simple', component: SimpleCmp}]);
+
+ cmp.activations = [];
+ cmp.deactivations = [];
+
+ router.navigateByUrl('/blank');
+ advance(fixture);
+
+ expect(cmp.activations.length).toEqual(1);
+ expect(cmp.activations[0] instanceof BlankCmp).toBe(true);
+
+ router.navigateByUrl('/simple');
+ advance(fixture);
+
+ expect(cmp.activations.length).toEqual(2);
+ expect(cmp.activations[1] instanceof SimpleCmp).toBe(true);
+ expect(cmp.deactivations.length).toEqual(2);
+ expect(cmp.deactivations[1] instanceof BlankCmp).toBe(true);
+ })));
+
describe('data', () => {
class ResolveSix implements Resolve {
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): number { return 6; }
diff --git a/tools/public_api_guard/router/index.d.ts b/tools/public_api_guard/router/index.d.ts
index 349ddde55e..ef970f01c7 100644
--- a/tools/public_api_guard/router/index.d.ts
+++ b/tools/public_api_guard/router/index.d.ts
@@ -180,8 +180,10 @@ export declare class RouterModule {
/** @stable */
export declare class RouterOutlet {
+ activateEvents: EventEmitter;
activatedRoute: ActivatedRoute;
component: Object;
+ deactivateEvents: EventEmitter;
isActivated: boolean;
outletMap: RouterOutletMap;
constructor(parentOutletMap: RouterOutletMap, location: ViewContainerRef, resolver: ComponentFactoryResolver, name: string);