Angular 2:使用静态s渲染表的组件和来自另一个组件的动态s

时间:2017-04-11 19:58:23

标签: angular angular2-template angular2-directives angular2-components

我有一个Angular 2组件,它使用小猫对象数据呈现一个漂亮的表。

由于某些列将在不同的组件中重用,我正在寻找一种方法将<td>提取到单独的组件中(dynamic-kitten-tds )。我无法移动呈现<td>kitten.name的{​​{1}},因为它们对kitten.lastWashed组件是唯一的:

猫邻base.component.html

cat-o-base

动态小猫tds.component.html

<table> <tbody> <tr *ngFor="let kitten of kittenBasket"> <td>{{ kitten.name }}</td> <dynamic-kitten-tds [value]="kitten"></dynamic-kitten-tds> <td>{{ kitten.lastWashed | date }}</td> </tr> </tbody> <table> 组件的整个模板如下所示:

dynamic-kitten-tds

限制1

我可能像这样使用<td *ngFor="let preference of kitten.preferences">{{ preference | json }}</td>

*ngFor

此限制来自必须作为<td>{{ kitten.name }}</td> <td *ngFor="let preference of kitten.preferences" [value]="preference"></td> <td>{{ kitten.lastWashed | date }}</td> 组件的一部分实现的业务逻辑。

限制2

代码必须产生有效的DOM发射。

问题

我如何实现它?使用辅助组件很好。使用特殊的结构指令也很好。

P.S

我查看了其他一些SO问题(例如this one),但没有找到完全匹配的问题定义。

1 个答案:

答案 0 :(得分:2)

如果使用辅助组件很好,我的想法是:

<强>动态outlet.ts

@Directive({selector: '[dynamicOutlet]'})
export class DynamicOutlet implements OnChanges, OnDestroy {
  @Input() dynamicOutlet: Type<any>;
  @Input() dynamicOutletModel: any;

  private componentRef: ComponentRef<any> = null;

  constructor(private vcRef: ViewContainerRef) {}

  ngOnChanges(changes: SimpleChanges) {
    this.vcRef.clear();
    this.componentRef = null;

    if (this.dynamicOutlet) {
      const elInjector = this.vcRef.parentInjector;
      const componentFactoryResolver = elInjector.get(ComponentFactoryResolver);

      const componentFactory = componentFactoryResolver.resolveComponentFactory(this.dynamicOutlet);
      this.componentRef = componentFactory.create(elInjector);

      this.componentRef.changeDetectorRef.detectChanges();
      this.componentRef.instance.model = this.dynamicOutletModel;
      this.vcRef.createEmbeddedView(this.componentRef.instance.template, { $implicit: this.dynamicOutletModel });
    }
  }

  ngOnDestroy() {
    if(this.componentRef) {
      this.vcRef.clear();
      this.vcRef = null;
    }
  }
}

<强> kitten.ts

@Component({
    selector: 'kitten-component',
    template: `
      <ng-template let-model>
        <td *ngFor="let preference of model.preferences">{{ preference | json }}</td>
      </ng-template>
    `
})
export class Kitten {
  @ViewChild(TemplateRef) template: TemplateRef<any>;

  model: any;
}

然后你可以像

一样使用它

查看

<ng-container *dynamicOutlet="kittenComp; model: kitten"></ng-container>

<强>组件

kittenComp = Kitten;

不要忘记将Kitten组件添加到entryComponents数组。

这是 Plunker Example