ngFor 中的 Angular 动态 View 子级

标签 angular ng-bootstrap

我正在尝试使用 ng-bootstrap 选项卡的 ngFor 中的 @ViewChild 获取组件实例,但是我什至只获取第一个组件实例尽管我正在更改选项卡以及组件及其输入

更新

我什至尝试过使用“@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来代替,它允许您将多个组件选择到一个数组中,如下所示:

@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 来选择组件,因此可以将其删除

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

关于ngFor 中的 Angular 动态 View 子级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43995502/

相关文章:

html - Angular 6 无法从 Assets 加载图像

javascript - Angular 4/5 - 使用动态配置实例化服务

angular - 禁用标记的 ng-bootstrap 不适用于其他日期选择器示例

angular - 如何将 bootstrap popover 绑定(bind)添加到我的 HTML?

angular - ng-bootstrap Datepicker 当前日期,如占位符

angular - 隔离测试 : how to test callback of an Observable

Angular mat-select,设置值有问题

angular - Strope.js 断开连接后无法重新连接

ng-bootstrap - 获取对嵌套在模态中的元素的引用

angular - 在 Angular 中模拟 NgbModal