我有一个第三方库组件,我试图通过在某个点添加一些额外的标记来自定义该组件。我正在使用结构指令来执行此操作,目前我正在使用渲染器以编程方式添加节点和设置节点样式,如下所示:
const headerDiv = this.newDiv();
el = this.nativeElement.querySelector('div.ui-dropdown-items-wrapper');
this.renderer.appendChild(el, this.renderer.createText('sometext'));
private newDiv(): Element {
return this.renderer.createElement('div');
}
Run Code Online (Sandbox Code Playgroud)
标记就像这样:
<div #containerDiv>
<child-component *myStructuralDirective>
</child-component>
</div>
Run Code Online (Sandbox Code Playgroud)
有没有办法直接在父组件的标记中定义<ng-template>并使用渲染器在某个点注入它?像这样的东西:
<div #containerDiv>
<child-component *myStructuralDirective>
</child-component>
</div>
<ng-template #footer>
<p>Some other markup</p>
</ng-template>
Run Code Online (Sandbox Code Playgroud)
然后在我选择的某个点将 #footer 的内容注入到子组件中。注意 - 我无法访问该子项,因为它是编译的第 3 方库。
其要点是,我试图看看是否有更好的方法将标记定义为模板变量,我可以在结构指令中使用该变量,访问该模板并将其注入子组件中的某个点。
编辑 - 我正在查看ViewContainerRef.insert,不幸的是,这只能根据其他ViewRefs 的位置插入模板。由于我无法更改第 3 方组件的标记,因此我可以定义 ang-container来标记插入点,并且只能使用 CSS 选择器。不确定是否有办法根据元素位置插入模板。我知道这是两个离散的概念(Angular View 抽象与直接 DOM 插入),所以我对这可以完成并不乐观!
是的,您可以使用以下方法将 ng-template 注入到您想要放置的任何位置:
1.) 使用ng-container
<div #containerDiv>
<child-component *myStructuralDirective></child-component>
// This will show your template
<ng-container [ngTemplateOutlet]="footer"></ng-container>
</div>
<ng-template #footer>
<p>Some other markup</p>
</ng-template>
Run Code Online (Sandbox Code Playgroud)
2.) 或者使用带有 ViewContainerRef 和 CreateEmbeddedView 的结构指令来注入它
Run Code Online (Sandbox Code Playgroud)a.)Supply the footer template on your childComponent. myStructuralDirective is now both a directive and an [] input that asks for a value. <child-component [myStructuralDirective]="footer"></child-component> b.) Use default ViewContainerRef declared on the constructor which pertains to your current view/screen which the template the template is attached example for this - it is attached on ChildComponentView @Directive({ selector: 'myStructuralDirective' }) export class MyStructuralDirective implements AfterViewInit { @Input() myStructuralDirective: TemplateRef<any>; constructor(private container: ViewContainerRef) {} ngAfterViewInit() { this.container.createEmbeddedView(this.myStructuralDirective); }}
3.) 或者在您的 ChildComponent 上提供 @Input() 传递页脚模板值
Run Code Online (Sandbox Code Playgroud)a.) <child-component *myStructuralDirective [footerTemplate]="footer"></child-component> b.) On the ChildComponent Class, declare its @Input() property @Component({ selector: 'child-component' }) export class ChildComponent { @Input() footerTemplate: TemplateRef<any>; } c.) On your ChildComponent Template, supply an ng-container to wherever you want it to be placed. <h1>Header</h1> <h1>Content</h1> <ng-container [ngTemplateOutlet]="footerTemplate"></ng-container>
4.) 或者你可以在你的ChildComponent上提供一个容器
a.) ChildComponent 示例模板
Run Code Online (Sandbox Code Playgroud)<p>Header</p> <p>Content</p> <div #container></div>b.) 使用需要来自组件的页脚模板值的 @Input() 在您的 ChildComponent 类上声明 ViewContainerRef 和 TemplateRef
Run Code Online (Sandbox Code Playgroud)@Component({...}) export class ChildComponent implements AfterViewInit { //From your template <div #container></div> @ViewChild('container', { read: ViewContainerRef }) container: ViewContainerRef; @Input() footerTemplate: TemplateRef<any>; ngAfterViewInit() { this.container.createEmbeddedView(this.footerTemplate); }}
您的 ng-template 现在将出现在您想要的位置。
| 归档时间: |
|
| 查看次数: |
6908 次 |
| 最近记录: |