ContentChildren с несколькими типами контента

Здравствуйте, я сейчас создаю таблицу, в которой можно использовать несколько типов столбцов. Я хочу использовать это как:

<my-table [rows] = "rows">
     <text-column [someParameters] = "here" header = "text"></text-column>
     <icon-column [someParameters] = "here" header = "icon"></icon-column>
</my-table>

text-column и icon-column - отдельные директивы.

В настоящее время у меня есть абстрактный класс под названием column, и, допустим, text-column и icon-column могут выглядеть примерно так:

   export abstract class Column
   {
       @Input() someParameters:string;
       @Input() header:string;
   }

   export class TextColumnDirective extends Column
   {
      //I do cool stuff here
   }

   export class IconColumnDirective extends Column
   {
      //I do different cool stuff   
   }

Моя таблица может выглядеть примерно так:

@Component({
   selector:'my-table',
   template: `
        <table>
            <thead>
                <tr>
                   <th *ngFor = "let column of columns">{{column.header}}</th>
                </tr>
            </thead>
        </table>
   `
})
export class MyTableComponent
{
    @ContentChildren(Column) columns:QueryList<any>;

    //I do cool stuff too
}

Итак, этот подход работает, если я не использую аннотацию, а просто вызываю ее только с текстовым столбцом, например @ContentChildren(TextColumnDirective) columns:QueryList<any>;. но получает только текстовый столбец и то же самое со столбцом значков. Как я могу это сделать, если позже я могу добавить разные типы директив для разных типов столбцов?

Вы должны посмотреть этот комментарий Github github.com/angular/angular/issues/8580#issuecomment-21833192‌ 0

Pierre Mallet 14.03.2018 14:28
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
7
1
3 055
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Хорошо, поэтому в комментариях выше мне сказали посмотреть комментарий по предоставленной ими ссылке.

Тем не менее, они правы в ответе, я отправлю код здесь для следующего человека.

<my-table [rows] = "rows">
  <text-column [someParameters] = "here" header = "text"></text-column>
  <icon-column [someParameters] = "here" header = "icon"></icon-column>
</my-table>
@Directive({
  selector: 'text-column',
  provider: [{provide:Column,useExisting:forwardRef(() => TextColumnDirective)})
})
export class TextColumnDirective extends Column
{
  // ...
}

@Directive({
  selector: 'icon-column',
  provider:[{provide:Column, useExisting:forwardRef(() => IconColumnDirective)})
})
export class IconColumnDirective extends Column
{
  // ...
}

Надеюсь, это поможет следующему человеку.

Здесь нужен forwardRef? В этом примере не используется netbasal.com/angular-components-tips-and-tricks-d9e725871d58 (совет № 2).

seangwright 08.08.2018 22:54

Ответ от @ 3xGuy правильный, но forwardRef(() => {}) не требуется, если предоставляемый тип не определен после декоратора или декорированного класса см. этот пост Angular In Depth

Обратите внимание, что этот подход можно использовать для ContentChildren или ViewChildren, ниже я использую ViewChildren

item.ts

import { Directive } from '@angular/core';

export class Item {
  color = '';
}

@Directive({
  selector: '[blueItem]',
  providers: [{ provide: Item, useExisting: BlueItemDirective }],
})
export class BlueItemDirective { // 'extends Item' is optional
  color = 'blue';
}

@Directive({
  selector: '[redItem]',
  providers: [{ provide: Item, useExisting: RedItemDirective }],
})
export class RedItemDirective { // 'extends Item' is optional
  color = 'red';
}

app.component.ts

import { Component, ViewChildren, QueryList } from '@angular/core';

import { Item } from './item';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Multiple View Child Types';

  // Note we query for 'Item' here and not `RedItemDirective'
  // or 'BlueItemDirective' but this query selects both types
  @ViewChildren(Item) viewItems: QueryList<Item>;

  itemColors: string[] = [];

  ngAfterViewInit() {
    this.itemColors = this.viewItems.map(item => item.color);
  }
}

app.component.html

<div redItem>Item</div>
<div blueItem>Item</div>
<div blueItem>Item</div>
<div blueItem>Item</div>
<div redItem>Item</div>

<h2>Colors of the above directives</h2>
<ul>
  <li *ngFor = "let color of itemColors">{{color}}</li>
</ul>

Вот StackBlitz, демонстрирующий это поведение в действии.

Другие вопросы по теме