假设我有以下超级简单的组件:
class MyComponent {
@Input()
simpleContent: string;
@ContentChild(TemplateRef)
content: TemplateRef<any>;
}
Run Code Online (Sandbox Code Playgroud)
<div>
<div *ngIf="simpleContent; else complexContent">{{simpleContent}}</div>
<ng-template #complexContent>
<ng-container [ngTemplateOutlet]="content"></ng-container>
</ng-template>
</div>
Run Code Online (Sandbox Code Playgroud)
根据用户的选择,它可以像这样使用:
<my-component simpleContent="Hello world!"></my-component>
Run Code Online (Sandbox Code Playgroud)
或者它可以像这样使用:
<my-component>
<ng-template>Hello world!</ng-template>
</my-component>
Run Code Online (Sandbox Code Playgroud)
虽然第二个选项允许嵌入 HTML 并因此更复杂的格式,但用户可以选择简单的方法,在大多数情况下只使用一个属性。
我想简化组件并去掉模板中的 if/else。我想象这样的事情:
class MyComponent {
@ContentChild(TemplateRef)
content: TemplateRef<any>;
@Input()
set simpleContent(value: string) {
this.content = new TemplateRef(value);
}
}
Run Code Online (Sandbox Code Playgroud)
<div>
<ng-container [ngTemplateOutlet]="content"></ng-container>
</div>
Run Code Online (Sandbox Code Playgroud)
显然这行不通,因为 new TemplateRef(value)是不可能的。
有没有办法在运行时动态创建一个基本的简单模板?
在这些示例中,我们实际上并没有“创建”templateRef,因为这需要角度渲染器工厂和大量额外代码来为新的 EmbeddedView 创建适当的注入器。我们只需要使用字符串值动态编辑模板即可。
使用 ng-container 模板 markdown 扩展 OP 的问题
<div>
<ng-container #container></ng-container>
</div>
<!-- Adding an empty template for later use -->
<ng-template #content><ng-content></ng-content></ng-template>
Run Code Online (Sandbox Code Playgroud)
那么组件的代码将如下所示
export class Component implements AfterViewInit{
@ViewChild("content") contentRef: TemplateRef<any>;
@ViewChild("container", {read: ViewContainerRef}) containerRef: ViewContainerRef;
divRef: HTMLElement;
value: string = "";
@Input()
set simpleContent(value: string) {
if(this.divRef){
this.divRef.innerHTML = this.value;
}
this.value = value;
}
constructor() {}
ngAfterViewInit(): void {
let div = document.createElement("div");
div.innerHTML = this.value;
var embeddedViewRef = this.contentRef.createEmbeddedView(this.containerRef);
this.containerRef.insert(embeddedViewRef);
embeddedViewRef.rootNodes[0].replaceWith(div);
this.divRef = div;
}
}
Run Code Online (Sandbox Code Playgroud)
在此示例中,我们获取对位于 EmbeddedView 根节点中的 ng-content 标记的引用,并将其替换为我们的本机 html 模板字符串。
由于我们在第一个示例中注入了 nativeElements,我想为什么不通过使用 ViewChild 和 ElementRef 获取它的引用来直接编辑第一个 div 标签。
@Component({
selector: "component",
template:`<div #ref></div>`
})
export class Component implements AfterViewInit{
@ViewChild("ref", {read: ElementRef}) tref: ElementRef;
value: string = "";
@Input()
set simpleContent(value: string) {
if(this.tref) this.tref.nativeElement.innerHTML = this.value;
this.value = value;
}
constructor() {}
ngAfterViewInit(): void {
this.tref.nativeElement.innerHTML = this.value;
}
}
Run Code Online (Sandbox Code Playgroud)
最后,由于它只是一个简单的字符串模板,我们想要注入到组件中,为什么不简单地在innerHTML上使用数据绑定
@Component({
selector: "component",
template:`<div [innerHTML]="value"></div>`
})
export class Component{
value: string = "";
@Input()
set simpleContent(value: string) {
this.value = value;
}
constructor() {}
}
Run Code Online (Sandbox Code Playgroud)
近两年后,我怀疑OP仍在等待答案。这个回复对我来说主要是一个挑战,但我自己在研究中学到了一些东西。喜欢这篇关于Angular 中 dom 操作技术的文章
希望这对那里的人有用
| 归档时间: |
|
| 查看次数: |
2817 次 |
| 最近记录: |