进样组件在* ngFor
问题描述:
我已经过在https://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html跟着教程和it's工作得很好:)进样组件在* ngFor
现在我想这样做更高级一点。 http://plnkr.co/edit/D1q7Al60m4UK1weRlcmQ?p=preview
我想要的是点击一个名字应该打开一个单独的行下方的细节。
例如。点击“Luke Skywalker”或“C3PO”应在第一行和第二行之间创建一行并显示详细信息。
我试图动态地添加“product-host”属性,但不能正常工作,因为指令期望属性存在。
<div *ngFor="let person of persons.results" fxFlex="50%" fxFlex.gt-sm="33%" person-host>
答
我会用ViewChildren
来实现它。有两种可能的方式:
1)只是通过指数在showPerson
功能
模板
<div *ngFor="let person of persons.results; let i = index" fxFlex="50%" fxFlex.gt-sm="33%" person-host>
<md-card (click)="showPerson(person, i)">{{person.name}}</md-card>
</div>
,然后用它来确定信息卡所需的地方
组件
activatedViewContainerRef: ViewContainerRef;
@ViewChildren(PersonInjectorDirective) personHosts: QueryList<PersonInjectorDirective>;
loadPerson(person, index) {
if(this.activatedViewContainerRef) {
this.activatedViewContainerRef.clear();
}
let componentFactory = this._componentFactoryResolver.resolveComponentFactory(PersonComponent);
this.activatedViewContainerRef = this.personHosts.find((item, i) => i === index).viewContainerRef;
let componentRef = this.activatedViewContainerRef.createComponent(componentFactory);
(<PersonComponent>componentRef.instance).person = person;
}
showPerson(person, index: number) {
this.loadPerson(person, index % 2 ? index : index + 1);
}
ngOnDestroy() {
if(this.activatedViewContainerRef) {
this.activatedViewContainerRef.clear();
}
}
2)您也可以建造它没有PersonInjectorDirective
。在这种情况下,你需要声明模板变量(#refs
):
<div *ngFor="let person of persons.results; let i = index" fxFlex="50%" fxFlex.gt-sm="33%" #refs>
<md-card (click)="showPerson(person, i)">{{person.name}}</md-card>
</div>
,改变ViewChildren
表达如下:
@ViewChildren('refs', { read: ViewContainerRef}) personHosts: QueryList<ViewContainerRef>;
THX一堆!真的很好解释!..是否有PersonInjectorDirective的优点/缺点? – Mackelito
我想如果你经常使用它,那么这是合理的。特别是如果您使用'PersonInjectorDirective'这样的类型来处理应用程序的某些架构部分之间的关系。许多团队坚持这种方法https://github.com/angular/material2/blob/master/src/lib/core/portal/portal-directives.ts#L28 – yurzui