Понимание ngTemplateOutlet, @ContentChild, ng-container в повторно используемом компоненте - PullRequest
0 голосов
/ 23 февраля 2019

Я трачу больше времени, пытаясь понять следующее сообщение в блоге Создание повторно используемых компонентов с NgTemplateOutlet в Angular

Рабочий код поста выше можно найти на stackblitz.

В компоненте UsageExample вызывается компонент представление карты или списка .Введены входные параметры items и mode , которые я очень хорошо понимаю.

Теперь я не понимаю, как

<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>

в шаблоне UsageExample заменяет

<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>

в шаблоне компонента CardOrListViewComponent.В компоненте CardOrListViewComponent две директивы объявлены

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

и используются в его шаблонах с *ngTemplateOutlet.

Как эти директивы были заменены на

<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>

в UsageExample компоненте.

Как *cardItem и *listItem соединяются с двумя @ContentChild директивы в CardOrListViewComponent компоненте.Их имена даже не похожи.

Я буду очень признателен, если кто-нибудь может дать мне подробное описание того, как это работает.

спасибо.

1 Ответ

0 голосов
/ 24 февраля 2019

Первый , Угловые структурные директивы имеют две формы, которые мы можем использовать:

1) версия с сахаром

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

2) версия без сахара

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

Вернемся к вашему примеру:

<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>

Во-вторых , обычная практика - получить ссылку на что-то в шаблоне через @ViewChild (- dren) | @ContentChild (-dren) decorators.

Мы можем запрашивать директивы, соответствующие элементам шаблона.Angular всегда соответствует обезвоженной версии нашего шаблона.Таким образом, директива:

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

соответствует шаблону:

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

Если вы не хотите, чтобы все возможные случаи касались запроса, следуйте этому ответу :

Теперь мы знаем, что с помощью запроса @ContentChild:

@ContentChild(CardItemDirective) cardItemTemplate;

мы получаем CardItemDirective экземпляр, но мы хотим получить TemplateRef, чтобы использовать его в *ngTemplateOutlet.

Вот где на помощь приходит опция read :

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

Наконец , имея TemplateRef, мы можем отрендерить его с помощью директивы ngTemplateOutlet и передать любой контекст, который мы хотим:

<div *ngFor="let item of items">
  <ng-container *ngTemplateOutlet="cardItemTemplate; context: {$implicit: item}">
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...