我正在尝试访问结构化指令中的“子”指令,以便可以在该指令中注入一些数据。但这总是导致未定义或注入错误。
我有以下html:
<app-table [dataSource]="data">
<button *customColumn="let row" [highlightRowOnClick]="row">
click here!
</button>
</app-table>
我想通过customColumn
将所有行注入到[highlightRowOnClick]
指令中,以便单击当前行时可以取消选择所有其他行
我想如何将所有行传递给指令:
(app-table
-> *customColumn
-> [highlightRowOnClick]
)。
我创建了一个Stackblitz,它在行选择有效的情况下重现了这个问题,但没有行取消选择。
我的想法
我知道我无法通过@ContentChildren
访问子组件,因为[highlightRowOnClick]
指令不是直接的子代,而是视图中的同级子{more here )。
我知道一个结构指令可以选择它的宿主元素(例如,一个属性指令,通过@Host
装饰器,请参见ngSwtich),但是这在其他方面是行不通的。这会导致注入器错误(no provider for 'customColumn' found
)。 (this is described here)
我可以使用服务来注入数据,但是当当前视图中有一个以上的表时,这可能会产生错误(由于该服务是单个实例,并且行可能完全相同,因此某些行可以互相覆盖,从而导致奇怪的选择问题(例如,两个表中都发生选择)。
我可以将行直接注入到[highlightRowOnClick]
指令中,但这将要求程序员每次都这样做。在我看来,您只想突出显示当前行是有意义的,我也不想将所有行都暴露给该位置的程序员,因为他已经可以通过[dataSouce]
来访问它们。所以我认为这不是最好的解决方案。
示例:
<app-table [dataSource]="rows">
<button *customColumn="let row; let rows=rows" [highlightRowOnClick]="row" allRows="rows">
click here!
</button>
</app-table>
有人知道我可以解决这个问题的更好方法吗?还是maby完全不同的方法?
答案 0 :(得分:1)
所有组件都包含在包装器组件中,可以将其注入HighlightRowOnClickDirective
constructor(@Optional() @Host() private wrap:WrapperComponent ){}
@Input('highlightRowOnClick')
row: Row;
@HostListener('click')
onClick(): void {
this.wrap.dataSource.forEach(x=>{
x.isSelected=(x==this.row)
})
}
}
请参见stackblitz
但是我真的不知道不使用变量“ indexSelected”并使用*ngFor="...;let i=index"
并作为参数传递的原因
更新。
我们可以在“ isSelected”行中有一个变量,或者在包装器“ indexSelected”中有一个唯一变量,然后将索引作为值传递
<div *ngFor="let row of dataSource;let i=index">
<div [class.selected]="i==indexSelected"> Hello world! </div>
<ng-container *ngFor="let col of colHeaders">
<ng-template *ngTemplateOutlet="col.template; context: { $implicit: i }"></ng-template>
</ng-container>
<br><br>
</div>
指令变为
@Input('highlightRowOnClick')index:number
@HostListener('click')
onClick(): void {
this.wrap.indexSelected=this.index
}