Angular 8:如何使用Multi-Content-Projection / Multiple-Transclusion slot两次?

Angular 8: How to use a Multi-Content-Projection / Multiple-Transclusion slot twice?

    <ng-template #menu><ng-content select="[slot='menu']"></ng-content></ng-template>
    <ng-template #content><ng-content select="[slot='content']"></ng-content></ng-template>

    <section *ngIf="landscape">
        <div class="global-ui-top">
            <ng-container *ngTemplateOutlet="menu"></ng-container> // 1st
        </div>
        <some-main-content>
            <ng-container *ngTemplateOutlet="content"></ng-container>
        </some-main-content>
        <div class="global-ui-bottom">
            <ng-container *ngTemplateOutlet="menu"></ng-container> // 2nd
        </div>
    </section>

    // portrait mode
    <section *ngIf="!landscape">
        ... pretty similar to above, also 2× menu, 1× content...

问题:我如何使用一个插槽两次?** 没有出现错误,如果我使用例如...

A <ng-container *ngTemplateOutlet="menu"></ng-container> A
B <ng-container *ngTemplateOutlet="menu"></ng-container> B

...但是插槽 get's only "picked once" 最后一次(两个 A 之间的标签保持为空)。换句话说,我的第一个 .global-ui-top 仍然是空的。

nb: 第 1+2 行中的 ng-detour 有助于解决有关插槽的 certain bug. Is is not doing harm, but also not helping (sadly the ng-template-contents don't get frozen after “first fill” ). Apparently there is a „uniqueness in the selection“ principle

有没有办法将菜单槽的内容填充到任何类型的模板中,并多次重复使用它(所有内容同时可见)?**

次要更新

似乎可以将 ng-template 引用捕获到 View Child 中:

   @ViewChild('menu', {static: true}) menuA: TemplateRef<any>;

...a console.dir() 向我展示了一个有效的 ElementRef,但我无法在 .html-Template 中输出它,即 <ng-template [ngTemplateOutlet]="menuA"></ng-template>

也许 this talk 会有用。

我的理解是 ng-content 不创建 内容,它只是将内容从一个部分移动到另一个部分。

我认为您的问题的解决方案是使用 ng-template。例如:

projected.component.ts

let instances = 0;

@Component({
  selector: 'app-projected',
template: `projected instance nr: {{ instanceId }}`
})
export class ProjectedComponent implements OnInit {
  instanceId: number;

  constructor() { }

  ngOnInit() {
    this.instanceId = ++instances;
  }

}

parent.component.ts

@Component({
  selector: 'app-parent',
  template: `
    <h3>Parent component</h3>

    <p>Using content #1</p>
    <ng-container *ngTemplateOutlet="content"></ng-container>

    <p>Using content #2</p>
    <ng-container *ngTemplateOutlet="content"></ng-container>
  `,
})
export class ParentComponent implements OnInit {
  @ContentChild('content', { read: TemplateRef }) content: TemplateRef<any>;

  constructor() { }

  ngOnInit() {
  }

}

重要的是:

<app-parent>
  <ng-template #content>
    <app-projected></app-projected>
  </ng-template>
</app-parent>

据我了解,ng-template里面的东西可以看作是蓝图。因此,每次使用 ng-template 时,您都会创建该蓝图的 新实例

Demo