Fra*_*cke 6 transclusion angular
我有一个外部组件(蓝绿色),其中包含一些带有我自己的ui-button按钮的flexbox 工具栏。还有一个内部组件,主要在棕色区域做它的事情(正如你所期望的)。
但是,根据内部组件(有几个来回切换的组件),必须在顶部/底部栏中插入更多上下文按钮。
(在外部使用绝对定位内容的 CSS 技巧不是一种选择,根据大小和便利性,外部工具栏的位置、大小等可能会有很大差异......)
我可以以某种方式传递对某些占位符(黑色方括号)的引用(就像常规内容投影/嵌入一样),并让它们由来自子组件的内容填充?
也许像ngTemplate[Outlet]这样的东西?和/或使用 @Output?
我想“向上传递”多于plain text或simple <b>rich</b> <i>html</i>理想情况下真正的角度模板代码,包括自定义组件,如
<ui-button icon="up.svg" (click)='...'></ui-button>
<ui-button icon="down.svg" (click)='...'></ui-button>
Run Code Online (Sandbox Code Playgroud)
...在外部组件的顶部栏中引导到:
<section class='some-flexbox'>
<ui-button icon="home.svg" (click)='...'></ui-button>
<ui-button icon="up.svg" (click)='...'></ui-button>
<ui-button icon="down.svg" (click)='...'></ui-button>
<ui-button icon="help.svg" (click)='...'></ui-button>
<ui-button icon="account.svg" (click)='...'></ui-button>
</section>
Run Code Online (Sandbox Code Playgroud)
想一想,添加的那些按钮的点击事件应该是找到了回家的路子,叹息……
更新
ngTemplateOutlet 听起来很有趣
我们还可以使用 ngTemplateOutlet 指令获取模板本身并在页面上的任何位置实例化它:
检查中,仍然不知道如何...
有两种可能的方法可以实现所需的行为。
这是这两种解决方案的快速解释。
1.使用PortalModule 演示链接
您可以在子组件的模板文件中定义模板。
<ng-template #templateForParent>
<button (click)="onTemplateBtnClicked('btn from child')">
Button from Child
</button>
</ng-template>
Run Code Online (Sandbox Code Playgroud)
然后使用装饰器在子组件文件中获取该模板的引用@viewChid。
@ViewChild("templateForParent", { static: true }) templateForParent: TemplateRef<any>;
Run Code Online (Sandbox Code Playgroud)
然后您可以TemplatePortal使用该模板引用创建一个门户,并在需要时将该门户传递给父级。
ngAfterViewInit(): void {
const templatePortal = new TemplatePortal(this.templateForParent, this.viewContainerRef);
setTimeout(() => {
this.renderToParent.emit(templatePortal);
});
}
Run Code Online (Sandbox Code Playgroud)
父组件的模板文件可能如下所示。
<div fxLayout="row" fxLayoutAlign="space-between center">
<button (click)="onBtnClick('one')">one</button>
<button (click)="onBtnClick('two')">two</button>
<ng-container [cdkPortalOutlet]="selectedPortal"></ng-container> <!-- pass the portal to the portalOutlet -->
<app-button-group (renderToParent)="selectedPortal = $event"></app-button-group>
<button (click)="onBtnClick('five')">five</button>
</div>
Run Code Online (Sandbox Code Playgroud)
就是这样。现在,您已将模板呈现给父组件,并且该组件仍然具有click事件绑定。单击事件处理程序是在子组件内部定义的。
使用ComponentPortal或DomPortal 的方式相同
2. 使用自定义指令 演示链接
您可以按如下方式创建一个角度指令,该指令会将元素从其宿主组件移动到宿主组件的父级。
import {Directive,TemplateRef,ElementRef,OnChanges,SimpleChanges,OnInit,Renderer2,DoCheck} from "@angular/core";
@Directive({
selector: "[appRenderToParent]"
})
export class RenderToParentDirective implements OnInit {
constructor(private elementRef: ElementRef<HTMLElement>) {}
ngOnInit(): void {
const childNodes = [];
this.elementRef.nativeElement.childNodes.forEach(node =>
childNodes.push(node)
);
childNodes.forEach(node => {
this.elementRef.nativeElement.parentElement.insertBefore(
node,
this.elementRef.nativeElement
);
});
this.elementRef.nativeElement.style.display = "none";
}
}
Run Code Online (Sandbox Code Playgroud)
然后您可以在任何组件上使用该指令。
<div fxLayout="row" fxLayoutAlign="space-between center">
<button (click)="onBtnClick('one')">one</button>
<button (click)="onBtnClick('two')">two</button>
<app-button-group appRenderToParent></app-button-group>
<button (click)="onBtnClick('five')">five</button>
</div>
Run Code Online (Sandbox Code Playgroud)
这里<app-button-group>有以下模板文件。
<button (click)="onBtnClick('three')">three</button>
<button (click)="onBtnClick('four')">four</button>
Run Code Online (Sandbox Code Playgroud)
因此,我们的指令会将按钮元素移动到其宿主的父组件。我们只是在 DOM 树中移动 DOM 节点,因此与这些元素绑定的所有事件仍然有效。
我们可以修改指令以接受类名或 id,并仅移动那些具有该类名或 id 的元素。
我希望这个能帮上忙。我建议阅读文档以获取有关 PortalModule 的更多信息。
| 归档时间: |
|
| 查看次数: |
1249 次 |
| 最近记录: |