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

Wrap Angular ngFor directive with another structural directive

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

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

其中 mySource 是具有 list 属性

的对象
mySource = { list: [1, 2, 3, 4, 5] };

因此,将 myDir 替换为 ngFor (*ngFor="let item of mySource.list") 会得到

My Directive #1
My Directive #2
My Directive #3
My Directive #4
My Directive #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 行包含 "My Directive #" 而 {{item}} 不不工作。 MyComponent 的 ng-template 似乎有问题。它接受 template 但不会传递 item.

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

使用$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

另见