用另一个结构指令包装 Angular ngFor 指令

Posted

技术标签:

【中文标题】用另一个结构指令包装 Angular ngFor 指令【英文标题】:Wrap Angular ngFor directive with another structural directive 【发布时间】:2018-06-05 07:04:21 【问题描述】:

我的 AppComponent 的模板(在 AppModule 中引导)是

<div *myDir="let item of mySource">
  My Directive #item
</div>

其中mySource 是具有list 属性的对象

mySource =  list: [1, 2, 3, 4, 5] ;

所以,用 ngFor (*ngFor="let item of mySource.list") 替换 myDir 会给我

我的指令 #1 我的指令 #2 我的指令 #3 我的指令 #4 我的指令 #5

我正在尝试将myDirmyComponent 成对实现,以在ngFor Angular 核心指令上提供模板化包装器,以便能够传递mySource(而不是mySource.list)并获得相同的结果.当然,最终的目标要复杂得多,但我需要用最小的例子来解决这个任务……做了什么?

my.directive.ts

import  MyComponent  from './my.component';

@Directive( selector: '[myDir][myDirOf]' )
export class MyDirective 
  private source;
  constructor(/* ... */)  
  @Input() set myDirOf(source) 
    this.source = source;
  
  ngOnInit() 
    // dynamic wrapping with MyComponent
    const templateView = this.templateRef.createEmbeddedView();
    const compFactory = this.resolver.resolveComponentFactory(MyComponent);
    const componentRef = this.viewContainer.createComponent(compFactory, null, this.viewContainer.injector, [templateView.rootNodes]);
    // passing MyDir params to Mycomponent's instance
    componentRef.instance.source = this.source;
    componentRef.instance.template = this.templateRef;
  

my.component.ts

@Component(
  selector: 'app-my',
  template: `
<div *ngFor="let item of source.list">
  <ng-template
    [ngTemplateOutlet]="template"
    [ngTemplateOutletContext]="
      item: item
    ">
  </ng-template>
</div>`
)
export class MyComponent implements OnInit 
  source;
  template;
  constructor()  

问题是我无法将item 传递回主机组件的模板,所以目前我只得到包含“我的指令#”的 5 行相同的行,而item 不起作用。 MyComponent 的ng-template 似乎有问题。它接受template,但不会通过item

我根据我目前的情况创建了一个可编辑的DEMO。另外,这是我需要的简单图表:

【问题讨论】:

【参考方案1】:

使用$implicit 将数据传递给item

my.component.html

<div *ngFor="let item of source.list">
  <ng-template
    [ngTemplateOutlet]="template"
    [ngTemplateOutletContext]="
      $implicit: item
    ">
  </ng-template>

</div>

你的模板

<div *myDir="let item of mySource">
  My Directive #item
</div>

等价于

<ng-template myDir let-item [myDirOf]="mySource">
  <div>
    My Directive #item
  </div>
</ng-template>

但如果模板变量 (let-item) 没有值,则默认采用$implicit

<ng-template myDir let-item="$implicit" [myDirOf]="mySource">
  <div>
    My Directive #item
  </div>
</ng-template>

DEMO

另见

What is $implicit in angular 2?

Angular2: How is ngfor expanded

【讨论】:

以上是关于用另一个结构指令包装 Angular ngFor 指令的主要内容,如果未能解决你的问题,请参考以下文章

Angular *ngFor 由一个单一的结构指令组成?还是两个?

Angular 2 编写结构指令,如 ngFor、iterableDiffer 可能会导致错误

Angular:如何使用 *ngFor 将指令绑定到元素

Angular2 内置指令 NgFor 和 NgIf 详解

Firebase列表的嵌套Angular2 ngFor指令[重复]

在 Angular 9 中动态加载 *ngFor 内的组件