diff --git a/README.md b/README.md index fbd0937..dcbbd35 100644 --- a/README.md +++ b/README.md @@ -17,11 +17,12 @@ This goal of this project is to help you get better at Angular and NgRx buy reso Angular Projection -Directive enhancemen +Directive enhancement +Directive enhancemen NgRx -Effect vs Selector +Effect vs Selector ## License diff --git a/apps/context-outlet-type/README.md b/apps/context-outlet-type/README.md new file mode 100644 index 0000000..eff16fd --- /dev/null +++ b/apps/context-outlet-type/README.md @@ -0,0 +1,45 @@ +

NgTemplateOutlet Strongly Typed

+ +## Information + +Angular offer the static function **ngTemplateContextGuard** to strongly type structural directive. + +However the context of **NgTemplateOutlet** type is **Object**. But which the help of the above guard, we can improve that behavior. + +## Statement + +In this exercice, we want to learn how to strongly typed our ng-template in our AppComponent. + +This exercice has two level of complexity. + +### Level 1: known Interface + +Currently we have the following piece of code. + +Unkown Person + +As we can see, name is of type "any". We want to infer the correct type. + +### Level 2: generic Interface + +Currently we have the following piece of code. + +Unkown Person + +As we can see, student is of type "any". We want to infer the correct type. + +But in this part, we can pass to ListComponent, a list of any types. And we still want the correct type to be infered. + +## Submitting your work + +1. Fork the project +2. clone it +3. npm install +4. **nx serve context-outlet-type** +5. _...work On it_ +6. Commit your work +7. Submit a PR with a title beginning with **Answer:4** that I will review and other dev can review. + +NgTemplateOutlet Strongly Typed + +_You can ask any question on_ Twitter diff --git a/apps/context-outlet-type/img/unknown-person.png b/apps/context-outlet-type/img/unknown-person.png new file mode 100644 index 0000000..9ab0a2e Binary files /dev/null and b/apps/context-outlet-type/img/unknown-person.png differ diff --git a/apps/context-outlet-type/img/unknown-student.png b/apps/context-outlet-type/img/unknown-student.png new file mode 100644 index 0000000..247a29e Binary files /dev/null and b/apps/context-outlet-type/img/unknown-student.png differ diff --git a/apps/context-outlet-type/src/app/app.component.ts b/apps/context-outlet-type/src/app/app.component.ts index ca29833..2683ba9 100644 --- a/apps/context-outlet-type/src/app/app.component.ts +++ b/apps/context-outlet-type/src/app/app.component.ts @@ -1,35 +1,29 @@ import { NgTemplateOutlet } from '@angular/common'; import { ChangeDetectionStrategy, Component } from '@angular/core'; -import { ListComponent, ListTemplateDirective } from './list.component'; -import { PersonComponent, PersonDirective } from './person.component'; +import { ListComponent } from './list.component'; +import { PersonComponent } from './person.component'; @Component({ standalone: true, - imports: [ - NgTemplateOutlet, - PersonDirective, - PersonComponent, - ListTemplateDirective, - ListComponent, - ], + imports: [NgTemplateOutlet, PersonComponent, ListComponent], selector: 'app-root', template: ` - + {{ name }}: {{ age }} - + {{ student.name }}: {{ student.age }} - {{ i }} - + - + {{ city.name }}: {{ city.country }} - {{ i }} - + `, changeDetection: ChangeDetectionStrategy.OnPush, diff --git a/apps/context-outlet-type/src/app/list.component.ts b/apps/context-outlet-type/src/app/list.component.ts index eeef366..7cafdcf 100644 --- a/apps/context-outlet-type/src/app/list.component.ts +++ b/apps/context-outlet-type/src/app/list.component.ts @@ -3,32 +3,10 @@ import { ChangeDetectionStrategy, Component, ContentChild, - Directive, Input, TemplateRef, } from '@angular/core'; -interface ListTemplateContext { - $implicit: TItem; - appList: TItem; - index: number; -} - -@Directive({ - selector: 'ng-template[appList]', - standalone: true, -}) -export class ListTemplateDirective { - @Input('appList') data!: TItem[]; - - static ngTemplateContextGuard( - dir: ListTemplateDirective, - ctx: unknown - ): ctx is ListTemplateContext { - return true; - } -} - @Component({ selector: 'list', standalone: true, @@ -50,6 +28,6 @@ export class ListTemplateDirective { export class ListComponent { @Input() list!: TItem[]; - @ContentChild(ListTemplateDirective, { read: TemplateRef }) + @ContentChild('listRef', { read: TemplateRef }) listTemplateRef!: TemplateRef; } diff --git a/apps/context-outlet-type/src/app/person.component.ts b/apps/context-outlet-type/src/app/person.component.ts index 5b6359d..4c33ae3 100644 --- a/apps/context-outlet-type/src/app/person.component.ts +++ b/apps/context-outlet-type/src/app/person.component.ts @@ -1,35 +1,11 @@ import { NgTemplateOutlet } from '@angular/common'; -import { - Component, - ContentChild, - Directive, - Input, - TemplateRef, -} from '@angular/core'; +import { Component, ContentChild, Input, TemplateRef } from '@angular/core'; interface Person { name: string; age: number; } -interface PersonContext { - $implicit: string; - age: number; -} - -@Directive({ - selector: 'ng-template[person]', - standalone: true, -}) -export class PersonDirective { - static ngTemplateContextGuard( - dir: PersonDirective, - ctx: unknown - ): ctx is PersonContext { - return true; - } -} - @Component({ standalone: true, imports: [NgTemplateOutlet], @@ -47,6 +23,6 @@ export class PersonDirective { export class PersonComponent { @Input() person!: Person; - @ContentChild(PersonDirective, { read: TemplateRef }) - personTemplateRef!: TemplateRef; + @ContentChild('#personRef', { read: TemplateRef }) + personTemplateRef!: TemplateRef; }