Understanding ngTemplateOutlet, @ContentChild, ng-container in Reusable Component

问题: I have been spending more time trying to understand the following blog post Creating Reusable Components with NgTemplateOutlet in Angular The working code of the post abo...

问题:

I have been spending more time trying to understand the following blog post Creating Reusable Components with NgTemplateOutlet in Angular

The working code of the post above can be found at stackblitz.

In the UsageExample component the card-or-list-view component is called. The items and mode input parameters are supplied which i understand very well.

Now what i don't understand is how

<ng-container *cardItem="let item">
        <h1>{{item.header}}</h1>
        <p>{{item.content}}</p>
      </ng-container>
      <span *listItem="let item">
        <h1>{{item.header}}</h1>
        <p>{{item.content}}</p>
      </span>

in the UsageExample template replaces

<ng-container *ngSwitchCase="'card'">
    <div *ngFor="let item of items" style="margin: 5px;border: black 1px solid">
      <ng-container *ngTemplateOutlet="cardItemTemplate; context: {$implicit: item}">
      </ng-container>
    </div>
  </ng-container>
  <ul *ngSwitchCase="'list'">
    <li *ngFor="let item of items">
      <ng-container *ngTemplateOutlet="listItemTemplate; context: {$implicit: item}"></ng-container>
    </li>
  </ul>

in the template of CardOrListViewComponent component. In the CardOrListViewComponent component, two directives are declared

@ContentChild(CardItemDirective, {read: TemplateRef}) cardItemTemplate;
  @ContentChild(ListItemDirective, {read: TemplateRef}) listItemTemplate;

and are used in its templates with *ngTemplateOutlet.

How do these directives got replaced by

<ng-container *cardItem="let item">
        <h1>{{item.header}}</h1>
        <p>{{item.content}}</p>
      </ng-container>
      <span *listItem="let item">
        <h1>{{item.header}}</h1>
        <p>{{item.content}}</p>
      </span>

in the UsageExample component.

How do *cardItem and *listItem connect to the two @ContentChild directives in CardOrListViewComponent component. Their names are not even similar.

I will really appreciate it if someone can give me a detail description of how it works.

thanks.


回答1:

First, Angular structural directives have two forms we can use:

1) sugared version

<div *ngIf="foo">bar</div>

2) de-sugared version

<ng-template [ngIf]="foo">
  <div>bar</div>
</ng-template>

Back to your example:

<ng-container *cardItem="let item">
  <h1>{{item.header}}</h1>                            sugar
  <p>{{item.content}}</p>
</ng-container>

       ||
       /

<ng-template cardItem let-item>
  <ng-container>
    <h1>{{item.header}}</h1>                         de-sugar
    <p>{{item.content}}</p>
  </ng-container>
</ng-template>

Secondly, it's common practice to get reference to something in template through @ViewChild(-dren)|@ContentChild(-dren) decorators.

We can query directives that match template elements. Angular always match de-sugared version of our template. So the directive:

@Directive({
  selector: '[cardItem]'
})
export class CardItemDirective {}

matches the template:

  selector: '[cardItem]' 
               ||
               /
<ng-template cardItem let-item>

If you don't want all possible cases about what we can query then follow this answer:

Now we know that by using @ContentChild query:

@ContentChild(CardItemDirective) cardItemTemplate;

we get CardItemDirective instance, but we want to get TemplateRef in order to use it in *ngTemplateOutlet.

Here's where read option comes to the rescue:

@ContentChild(CardItemDirective, {read: TemplateRef}) cardItemTemplate;
                                     /
         please give us TemplateRef instance from the element 
         that matches CardItemDirective selector

Finally, having TemplateRef we can render it with the help of ngTemplateOutlet directive and pass any context we want:

<div *ngFor="let item of items">
  <ng-container *ngTemplateOutlet="cardItemTemplate; context: {$implicit: item}">
  • 发表于 2019-02-25 08:48
  • 阅读 ( 550 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除