我有一个呈现DOM的组件,该组件应位于svg标记内:
import { Component, Input } from '@angular/core';
@Component({
selector: 'g[hello]',
template: `<svg:text x="50%" y="50%" text-anchor="middle">Hello, {{name}}</svg:text>`,
styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent {
@Input() name: string;
}
Run Code Online (Sandbox Code Playgroud)
当我静态实例化它时,一切正常(文本在页面上可见):
<svg>
<svg:g hello name="Static component"></svg:g>
</svg>
Run Code Online (Sandbox Code Playgroud)
生成以下DOM:
<svg _ngcontent-iej-c129="">
<g _ngcontent-iej-c129="" hello="" name="Static component" _nghost-iej-c130="" ng-reflect-name="Static component">
<text _ngcontent-iej-c130="" text-anchor="middle" x="50%" y="50%">
Hello, Static component
</text>
</g>
</svg>
Run Code Online (Sandbox Code Playgroud)
当我尝试使用ComponentFactoryResolver动态实例化组件时,问题就开始了:
<svg>
<ng-container #container></ng-container>
</svg>
Run Code Online (Sandbox Code Playgroud)
import { Component, ViewChild, ViewContainerRef, ComponentFactoryResolver, OnInit } from '@angular/core';
import { HelloComponent } from './hello.component'
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
@ViewChild('container', {read: ViewContainerRef, static: true}) container: ViewContainerRef;
constructor(private componentFactoryResolver: ComponentFactoryResolver) {
}
ngOnInit() {
// Instantiating HelloComponent dynamically
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(HelloComponent)
const componentRef = this.container.createComponent(componentFactory);
componentRef.instance.name = 'Dynamic component'
}
}
Run Code Online (Sandbox Code Playgroud)
产生的DOM看起来还不错,但是由于某些原因,该文本在页面上不可见:
<svg _ngcontent-iej-c129="">
<!---->
<g hello="" _nghost-iej-c130="">
<text _ngcontent-iej-c130="" text-anchor="middle" x="50%" y="50%">
Hello, Dynamic component
</text>
</g>
</svg>
Run Code Online (Sandbox Code Playgroud)
我假设这里有两个问题:
第一个问题的答案是使用svg而不是g对元素进行分组。
在您的具体示例中,这意味着更改选择器:
@Component({
selector: 'svg[hello]',
template: `<svg:text x="50%" y="50%" text-anchor="middle">Hello, {{name}}</svg:text>`,
styles: [`h1 { font-family: Lato; }`]
})
Run Code Online (Sandbox Code Playgroud)
和app.component.html:
<svg>
<svg hello name="Static component"></svg>
</svg>
Run Code Online (Sandbox Code Playgroud)
现在让我们来看第二个问题。为什么会这样呢?
您的选择器不包含svg名称空间。为了正确呈现它,选择器应为svg:g[hello]。
但是,由于一个老问题是一直存在,因为角5是不可能的
更多细节在这里和这里。
如该评论中所述,这里的主要问题是Angular选择器不能包含用于创建元素的名称空间。
选择器svg:g[hello]将解析为g[hello],结果Angular将使用document.createElement而不是document.createElementNS创建新元素。
为什么要使用svg[hello]作品?
因为如果我们使用选择器,svg[hello]则会将其解析到<svg child>Angular 隐式提供的名称空间:
'svg': new HtmlTagDefinition({implicitNamespacePrefix: 'svg'}),
Run Code Online (Sandbox Code Playgroud)