结构指令获取子指令

时间:2019-08-09 06:52:18

标签: angular typescript angular-directive

我正在尝试访问结构化指令中的“子”指令,以便可以在该指令中注入一些数据。但这总是导致未定义或注入错误。

我有以下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完全不同的方法?

1 个答案:

答案 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
  }

请参阅another stackblitz