компонент рендеринга, переданный через @ContentChildren или @ContentChild

#angular

#angular

Вопрос:

Я делаю проекцию контента с помощью @ContentChildren.

Теперь у меня есть необходимость поместить компоненты из запроса contentchildren куда-нибудь, где я выберу это место. Я также должен добавить дополнительный разделитель, если он не последний в массиве. Итак, причина в том, что на основе заданного списка компонентов (дочерних элементов контента) Мне нужно создать новый список с дополнительными компонентами между ними…

Как это можно сделать в Angular? Я искал динамическое внедрение компонента, но оно всегда начинается с типа компонента, используемого для рендеринга компонента. Но в этом случае у меня уже есть компоненты в массиве запросов ContentChildren…

Комментарии:

1. Знаете ли вы тип проектируемых компонентов? Я имею в виду, вы пытаетесь реализовать компонент, подобный tabs, который включает компоненты дочерних вкладок?

2. Я думаю, что требуется дополнительная информация, которая поможет вам. По какой причине вам нужно изменить расположение компонентов? Если они находятся в ContentChildren, я предполагаю, что они уже определены где-то в шаблоне. Все ли компоненты отправляются в одно и то же место? Лучшим вариантом было бы предоставить некоторый код, чтобы получить представление…

3. Я знаю тип yes, и у меня даже уже есть компоненты в массиве ContentChildren (запрос)… Я могу перебирать эти компоненты и распечатывать свойства. Мне просто нужно отобразить его где-нибудь в представлении так, как я хочу…

4. Причина в том, что на основе заданного списка мне нужно создать новый список с дополнительными компонентами между ними…

5. Я думаю, вам следует прочитать о ng-template и использовании его createEmbeddedView() метода.

Ответ №1:

Вот рабочее решение

Чтобы смоделировать то, что вы хотите реализовать, я реализовал два компонента, tabs и tab

Вы можете использовать эти компоненты следующим образом

 <my-tabs>
  <my-tab text="Tab 1"></my-tab>
  <my-tab text="Tab 2"></my-tab>
  <my-tab text="Tab 3"></my-tab>
</my-tabs>

<div>------------------</div>

<my-tab text="This is rendered itself" [single]="true"></my-tab>
  

Внутри TabComponent я обернул ng-content с помощью ng-template , чтобы я мог внедрить его в компонент с помощью @ViewChild(TemplateRef) content .

 @Component({
  selector: 'my-tab',
  template: `
    <ng-template>
      {{text}}
    </ng-template>

    <ng-container *ngIf="single">
      <ng-container *ngTemplateOutlet="content"></ng-container>
    </ng-container>
  `
})
export class TabComponent {
  @ViewChild(TemplateRef) content;

  @Input() text;
  @Input() single = false; // this will allow to use this component on its own
}
  

TabsComponent

 @Component({
  selector: 'my-tabs',
  template: `
    <div *ngFor="let tab of tabs; let isLast = last">
      <ng-container *ngTemplateOutlet="tab.content"></ng-container>
      <hr *ngIf="!isLast">
    </div>
  `,
})
export class TabsComponent  {
  @ContentChildren(TabComponent) tabs: QueryList<TabComponent>;
}
  

Вы можете использовать директиву tab.content within *ngTemplateOutlet .

<ng-container *ngTemplateOutlet="tab.content"></ng-container>

Комментарии:

1. В моем примере TabComponent является компонентом Remark и уже имеет определенный html. Таким образом, html дочернего компонента уже определен и не является универсальным.

2. Вы все еще можете обернуть его с помощью ng-template и позволить TabsComponent выполнять рендеринг.

3. ты спаситель!

4. @stephan.peters спасибо, я рад, что это решило вашу проблему 🙂

5. Все еще проблема: я вложил компонент RemarkComponent (TabComponent) в ng-шаблон. Но теперь он не хочет показывать, использую ли я его вне списка.