Angular 8:如何使用Multi-Content-Projection / Multiple-Transclusion slot两次?
Angular 8: How to use a Multi-Content-Projection / Multiple-Transclusion slot twice?
- 我有一个 Angular 8.2 项目,它有两种不同的显示模式(横向|纵向)
- 在每个工具栏中,顶部和底部都有一个工具栏,围绕着主要内容。
-
menu
以及主要的 content
是特定于模块的,因此我正在使用插槽。换句话说:五分之一的不同可能父组件使用此组件并提供 main
内容和一个(单独不同的)menu
,使用 angular content projection.
<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-content>
或 <ng-template
上的奇特标志? ("static"?!?)
- 或者首先以某种方式将插槽的内容打入
@viewChild()
(在 component.ts 中)...
- 否则...?
次要更新
似乎可以将 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
时,您都会创建该蓝图的 新实例 。
- 我有一个 Angular 8.2 项目,它有两种不同的显示模式(横向|纵向)
- 在每个工具栏中,顶部和底部都有一个工具栏,围绕着主要内容。
-
menu
以及主要的content
是特定于模块的,因此我正在使用插槽。换句话说:五分之一的不同可能父组件使用此组件并提供main
内容和一个(单独不同的)menu
,使用 angular content projection.
<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-content>
或<ng-template
上的奇特标志? ("static"?!?) - 或者首先以某种方式将插槽的内容打入
@viewChild()
(在 component.ts 中)... - 否则...?
次要更新
似乎可以将 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
时,您都会创建该蓝图的 新实例 。