Skip to content

Commit 8b837ce

Browse files
committed
chore: create directives person & templateOutlet
1 parent 1572100 commit 8b837ce

File tree

4 files changed

+88
-7
lines changed

4 files changed

+88
-7
lines changed

apps/angular/4-typed-context-outlet/src/app/app.component.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ import { NgTemplateOutlet } from '@angular/common';
22
import { ChangeDetectionStrategy, Component } from '@angular/core';
33
import { ListComponent } from './list.component';
44
import { PersonComponent } from './person.component';
5+
import { PersonDirective } from './person.directive';
56

67
@Component({
7-
imports: [NgTemplateOutlet, PersonComponent, ListComponent],
8+
imports: [NgTemplateOutlet, PersonComponent, ListComponent, PersonDirective],
89
selector: 'app-root',
910
template: `
1011
<person [person]="person">
11-
<ng-template #personRef let-name let-age="age">
12+
<ng-template #personRef let-name let-age="age" person>
1213
{{ name }}: {{ age }}
1314
</ng-template>
1415
</person>
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
import { NgTemplateOutlet } from '@angular/common';
1+
import { CommonModule, NgTemplateOutlet } from '@angular/common';
22
import { Component, ContentChild, Input, TemplateRef } from '@angular/core';
3+
import { PersonDirective } from './person.directive';
4+
import { AppTemplateOutletDirective } from './templateOutlet.directive';
35

4-
interface Person {
6+
export interface IPerson {
57
name: string;
68
age: number;
79
}
810

911
@Component({
10-
imports: [NgTemplateOutlet],
12+
imports: [NgTemplateOutlet, AppTemplateOutletDirective, CommonModule],
1113
selector: 'person',
1214
template: `
1315
<ng-container
@@ -20,8 +22,8 @@ interface Person {
2022
`,
2123
})
2224
export class PersonComponent {
23-
@Input() person!: Person;
25+
@Input() person!: IPerson;
2426

25-
@ContentChild('#personRef', { read: TemplateRef })
27+
@ContentChild(PersonDirective, { read: TemplateRef })
2628
personTemplateRef!: TemplateRef<unknown>;
2729
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Directive } from '@angular/core';
2+
3+
interface IPersonContext {
4+
$implicit: string;
5+
name: string;
6+
age: number;
7+
}
8+
9+
@Directive({
10+
selector: 'ng-template[person]',
11+
standalone: true,
12+
})
13+
export class PersonDirective {
14+
static ngTemplateContextGuard(
15+
dir: PersonDirective,
16+
ctx: unknown,
17+
): ctx is IPersonContext {
18+
return true;
19+
}
20+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import {
2+
Directive,
3+
EmbeddedViewRef,
4+
Injector,
5+
Input,
6+
OnChanges,
7+
SimpleChanges,
8+
TemplateRef,
9+
ViewContainerRef,
10+
} from '@angular/core';
11+
12+
@Directive({
13+
selector: '[ngTemplateOutlet]',
14+
standalone: true,
15+
})
16+
// The directive is now waiting for a specific Type.
17+
export class AppTemplateOutletDirective<T> implements OnChanges {
18+
private _viewRef: EmbeddedViewRef<T> | null = null;
19+
20+
@Input() public ngTemplateOutletContext: T | null = null;
21+
22+
@Input() public ngTemplateOutlet: TemplateRef<T> | null = null;
23+
24+
@Input() public ngTemplateOutletInjector: Injector | null = null;
25+
26+
constructor(private readonly _viewContainerRef: ViewContainerRef) {}
27+
28+
ngOnChanges(changes: SimpleChanges) {
29+
if (changes['ngTemplateOutlet'] || changes['ngTemplateOutletInjector']) {
30+
const viewContainerRef = this._viewContainerRef;
31+
32+
if (this._viewRef) {
33+
viewContainerRef.remove(viewContainerRef.indexOf(this._viewRef));
34+
}
35+
36+
if (this.ngTemplateOutlet) {
37+
const {
38+
ngTemplateOutlet: template,
39+
ngTemplateOutletContext: context,
40+
ngTemplateOutletInjector: injector,
41+
} = this;
42+
this._viewRef = viewContainerRef.createEmbeddedView(
43+
template,
44+
context,
45+
injector ? { injector } : undefined,
46+
) as EmbeddedViewRef<T> | null;
47+
} else {
48+
this._viewRef = null;
49+
}
50+
} else if (
51+
this._viewRef &&
52+
changes['ngTemplateOutletContext'] &&
53+
this.ngTemplateOutletContext
54+
) {
55+
this._viewRef.context = this.ngTemplateOutletContext;
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)