Здравствуйте, я сейчас создаю таблицу, в которой можно использовать несколько типов столбцов. Я хочу использовать это как:
<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>;.
но получает только текстовый столбец и то же самое со столбцом значков. Как я могу это сделать, если позже я могу добавить разные типы директив для разных типов столбцов?





Хорошо, поэтому в комментариях выше мне сказали посмотреть комментарий по предоставленной ими ссылке.
Тем не менее, они правы в ответе, я отправлю код здесь для следующего человека.
<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).
Ответ от @ 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, демонстрирующий это поведение в действии.
Вы должны посмотреть этот комментарий Github github.com/angular/angular/issues/8580#issuecomment-21833192 0