angular ngFor 中的动态视图子项

angular dynamic view child in ngFor

我正在尝试使用 @ViewChild 获取组件实例,它位于 ng-bootstrap 选项卡的 ngFor 中,但是我只获取了第一个组件实例,即使我正在更改选项卡以及 component 及其 inputs

更新

我什至尝试过使用“@ViewChildren”,但结果不一致。

请参阅 Plunker2 以了解其行为方式。

我是否可以访问 ngFor 中的特定组件实例,或者我是否遗漏了什么?

版本信息:

Angular: 2.4.0;
ng-bootstrap: 1.0.0-alpha.20

组件:

@Component({
  selector: 'my-app',
  template: `
    <ngb-tabset (tabChange)="tabChanged($event)">
      <ngb-tab *ngFor="let item of tabs;let tIdx = index;" [title]="item.slice(0,10)">
        <template ngbTabContent>
          <app-grid [content]="item" #grid></app-grid>
        </template>
      </ngb-tab>
    </ngb-tabset>
  `
})

export class App {
  @ViewChild('grid') grid: GridComponent;
  tabs=[
    `Raw denim you probably haven't heard of them jean shorts Austin.`,
      `Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid.`,
      `Mustache cliche tempor, williamsburg carles vegan helvetica.`]
  tabChanged(event){
    debugger;
    console.log(this.grid);
    alert(this.grid.content);
  }
}  

演示

Plunker
Plunker2

编辑:

这些组件是基于模板的,只有在您访问每个选项卡后才会实例化。您可以使用网格组件 onInit 内的 console.log 对其进行测试。

所以它们不能从一开始就可用(当主应用程序组件被实例化时)。此时仅创建第一个选项卡。

要访问组件实例,您需要先确保以某种方式激活所有选项卡。

您可以使用 EventEmitter 进行跟踪,但随后您需要手动从网格中发出事件 - 虽然这是一种灵活的方法。您可以发出内容以及组件实例本身

export class GridComponent implements OnInit { 
 @Input() content:string;
 @Output() contentChanged = new EventEmitter<string>();

 ngOnInit(){
  setInterval(() => {
    this.content = this.content + ' xxx ';
    this.contentChanged.emit({ content: this.content, controller: this });
  }, 2000);
}

然后分配事件处理程序

<template ngbTabContent>
  <app-grid [content]="item" (contentChanged)="changed(tIdx, $event)"></app-grid>
</template>

你可以用它来跟踪

changed(tIdx, { content, controller }) {
  console.log(tIdx + " : " + content);
  console.log(controller);
}

参见 plnkr.co/edit/c6m3QyDSd0fWpoJUvTh7?p=preview

原刊

您可以改用 @ViewChildren,这样您就可以 select 将多个组件放入一个数组中,如下所示:

@ViewChildren(GridComponent) grids: QueryList<GridComponent>; // select by component type but you could also use css - using id however is not ok for multiple items

tabChanged(event){
  debugger;
  console.log(this.grids.toArray());
  alert(this.grids.toArray().map(g => g.content));
}

并且由于您不再将 id 用于 select 组件,您可以将其删除

<template ngbTabContent>
  <app-grid [content]="item"></app-grid>
</template>