【问题标题】:Structural directive get child directive结构指令获取子指令
【发布时间】:2019-12-16 21:14:38
【问题描述】:

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

我有以下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)。

  • 我知道结构指令可以选择它的宿主元素(例如,属性指令,请参阅 ngSwtich,通过 @Host 装饰器),但反过来就不行了。这会导致喷油器错误 (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>

有谁知道我可以解决这个问题的更好方法吗?或者可能是一种完全不同的方法?

【问题讨论】:

    标签: angular typescript angular-directive


    【解决方案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

    【讨论】:

    • 谢谢,我没有想到这个解决方案! 'indexSelected' 变量是什么意思?我认为在那个地方向用户公开所有行不是一个好方法,因为用户应该只能控制 [dataSource] 中的行
    • 啊,我明白了。提供行更好,因为您可以将行数据传递给函数(例如 Angular 材质选项菜单 (material.angular.io/components/menu/overview))。但感谢您的洞察力!
    猜你喜欢
    • 2017-10-15
    • 1970-01-01
    • 1970-01-01
    • 2019-04-08
    • 1970-01-01
    • 2019-02-01
    • 1970-01-01
    • 2019-04-16
    • 2015-09-24
    相关资源
    最近更新 更多