diff --git a/apps/angular/4-typed-context-outlet/src/app/app.component.ts b/apps/angular/4-typed-context-outlet/src/app/app.component.ts
index 23be9dac6..0cb7695c2 100644
--- a/apps/angular/4-typed-context-outlet/src/app/app.component.ts
+++ b/apps/angular/4-typed-context-outlet/src/app/app.component.ts
@@ -2,13 +2,14 @@ import { NgTemplateOutlet } from '@angular/common';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ListComponent } from './list.component';
import { PersonComponent } from './person.component';
+import { PersonDirective } from './person.directive';
@Component({
- imports: [NgTemplateOutlet, PersonComponent, ListComponent],
+ imports: [NgTemplateOutlet, PersonComponent, ListComponent, PersonDirective],
selector: 'app-root',
template: `
-
+
{{ name }}: {{ age }}
diff --git a/apps/angular/4-typed-context-outlet/src/app/person.component.ts b/apps/angular/4-typed-context-outlet/src/app/person.component.ts
index 59eb00ab1..2b45f50e2 100644
--- a/apps/angular/4-typed-context-outlet/src/app/person.component.ts
+++ b/apps/angular/4-typed-context-outlet/src/app/person.component.ts
@@ -1,13 +1,15 @@
-import { NgTemplateOutlet } from '@angular/common';
+import { CommonModule, NgTemplateOutlet } from '@angular/common';
import { Component, ContentChild, Input, TemplateRef } from '@angular/core';
+import { PersonDirective } from './person.directive';
+import { AppTemplateOutletDirective } from './templateOutlet.directive';
-interface Person {
+export interface IPerson {
name: string;
age: number;
}
@Component({
- imports: [NgTemplateOutlet],
+ imports: [NgTemplateOutlet, AppTemplateOutletDirective, CommonModule],
selector: 'person',
template: `
;
}
diff --git a/apps/angular/4-typed-context-outlet/src/app/person.directive.ts b/apps/angular/4-typed-context-outlet/src/app/person.directive.ts
new file mode 100644
index 000000000..6c5c4cc51
--- /dev/null
+++ b/apps/angular/4-typed-context-outlet/src/app/person.directive.ts
@@ -0,0 +1,20 @@
+import { Directive } from '@angular/core';
+
+interface IPersonContext {
+ $implicit: string;
+ name: string;
+ age: number;
+}
+
+@Directive({
+ selector: 'ng-template[person]',
+ standalone: true,
+})
+export class PersonDirective {
+ static ngTemplateContextGuard(
+ dir: PersonDirective,
+ ctx: unknown,
+ ): ctx is IPersonContext {
+ return true;
+ }
+}
diff --git a/apps/angular/4-typed-context-outlet/src/app/templateOutlet.directive.ts b/apps/angular/4-typed-context-outlet/src/app/templateOutlet.directive.ts
new file mode 100644
index 000000000..8877be9c5
--- /dev/null
+++ b/apps/angular/4-typed-context-outlet/src/app/templateOutlet.directive.ts
@@ -0,0 +1,58 @@
+import {
+ Directive,
+ EmbeddedViewRef,
+ Injector,
+ Input,
+ OnChanges,
+ SimpleChanges,
+ TemplateRef,
+ ViewContainerRef,
+} from '@angular/core';
+
+@Directive({
+ selector: '[ngTemplateOutlet]',
+ standalone: true,
+})
+// The directive is now waiting for a specific Type.
+export class AppTemplateOutletDirective implements OnChanges {
+ private _viewRef: EmbeddedViewRef | null = null;
+
+ @Input() public ngTemplateOutletContext: T | null = null;
+
+ @Input() public ngTemplateOutlet: TemplateRef | null = null;
+
+ @Input() public ngTemplateOutletInjector: Injector | null = null;
+
+ constructor(private readonly _viewContainerRef: ViewContainerRef) {}
+
+ ngOnChanges(changes: SimpleChanges) {
+ if (changes['ngTemplateOutlet'] || changes['ngTemplateOutletInjector']) {
+ const viewContainerRef = this._viewContainerRef;
+
+ if (this._viewRef) {
+ viewContainerRef.remove(viewContainerRef.indexOf(this._viewRef));
+ }
+
+ if (this.ngTemplateOutlet) {
+ const {
+ ngTemplateOutlet: template,
+ ngTemplateOutletContext: context,
+ ngTemplateOutletInjector: injector,
+ } = this;
+ this._viewRef = viewContainerRef.createEmbeddedView(
+ template,
+ context,
+ injector ? { injector } : undefined,
+ ) as EmbeddedViewRef | null;
+ } else {
+ this._viewRef = null;
+ }
+ } else if (
+ this._viewRef &&
+ changes['ngTemplateOutletContext'] &&
+ this.ngTemplateOutletContext
+ ) {
+ this._viewRef.context = this.ngTemplateOutletContext;
+ }
+ }
+}