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

Fra*_*cke 4 angular angular-content-projection

  • 我有一个 Angular 8.2 项目,它有两种不同的显示模式(横向|纵向)
  • 在每个内部,顶部和底部都有一个工具栏,围绕着主要内容。
  • Themenu和 maincontent是特定于模块的,因此我使用的是插槽。换句话说:五分之一的不同可能的父组件使用这个组件并提供main内容和一个(单独不同的)menu,使用角度内容投影
    <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...
Run Code Online (Sandbox Code Playgroud)

问题:我怎样才能使用一个插槽两次?** 没有错误出现,如果我使用 eg..

A <ng-container *ngTemplateOutlet="menu"></ng-container> A
B <ng-container *ngTemplateOutlet="menu"></ng-container> B
Run Code Online (Sandbox Code Playgroud)

...然而,插槽 get 只在最后一次“选择一次”(两个 A 之间的标签保持为空)。换句话说,我的第一个.global-ui-top仍然是空的。

注意:ng-detour第 1+2 行中的这有助于解决某个错误。是没有造成伤害,但也没有帮助(遗憾的是ng-template-contents 在“第一次填充”后不会被冻结)。显然,关于插槽有一个“选择的唯一性”原则

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

  • 也许是一个花哨的旗帜<ng-content><ng-template?(“静止的”?!?)
  • 或者首先以某种方式将插槽的内容重击到@viewChild()(在 component.ts 中)...
  • 别的...?

小更新

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

   @ViewChild('menu', {static: true}) menuA: TemplateRef<any>;
Run Code Online (Sandbox Code Playgroud)

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

And*_*tej 5

也许这次谈话会有用。

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

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

投影.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;
  }

}
Run Code Online (Sandbox Code Playgroud)

父组件.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() {
  }

}
Run Code Online (Sandbox Code Playgroud)

这是重要的事情:

<app-parent>
  <ng-template #content>
    <app-projected></app-projected>
  </ng-template>
</app-parent>
Run Code Online (Sandbox Code Playgroud)

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

演示