我想创建一个通用的html片段组件。我们的想法是将html片段存储在db中的某个地方,以及应该应用于它们的样式。
我可以轻松设置innerHtml,将html结构插入到视图模板的基本元素中,但如何在视图模板中动态插入<style>
标记?
这就是我所拥有的:
@Component({
moduleId: module.id,
selector: 'htmlFragment',
styleUrls: ['html-fragment.css'],
templateUrl:'html-fragment.html'
})
export class HtmlFragmentComponent {
@Input() htmlContent: string;
@Input() styleContent: string;
}
以下是视图模板:
<style [innerHTML]="styleContent"></style>
<div [innerHTML]="htmlContent"></div>
然后我试图像这样使用它:
<htmlFragment [htmlContent]='dHtml' [styleContent]="sHtml"></htmlFragment>
其中:
dHtml: string = '<div>hello this is html<ul><li>bla bla</li><li>bla bla 2</li></ul></div>';
sHtml: string = 'ul{list-style-type: none;}';
html片段在这里正确注入:
<div [innerHTML]="htmlContent"></div>
但是这里的样式元素:
<style [innerHTML]="styleContent"></style>
无效。有没有办法做到这一点?
答案 0 :(得分:9)
它不能在模板本身中完成(Angular模板编译器不允许它,并且只删除任何{
"one": "two",
"key": "value"
}
标记),但它可以在组件中以编程方式完成:
<style>
答案 1 :(得分:1)
默认情况下,Angular将吞食<style>
元素并将其放入默认的Angular CSS管道中。您可以通过以下方法绕过此方法:
@Component({
template: `<div [innerHTML]="styles"></div>`
})
export class OutputStyleTagComponent implements OnInit {
public styles: SafeHtml;
constructor(
private sanitizer: DomSanitizer
) {}
ngOnInit() {
this.styles = this.sanitizer.bypassSecurityTrustHtml(`
<style>
.my-styles {
...
}
</style>
`);
}
}
它有缺点,例如需要包装div容器。您还必须确保您不允许用户在此标记中提交内容,因为它使您容易受到XSS攻击。如果必须的话,则需要先确保内容安全,然后再将其传递给bypassSecurityTrustHtml。
答案 2 :(得分:1)
与OP有关,尽管为了完整起见,我不建议使用下面的旁路(或该线程中的任何其他旁路)。推荐的解决方案是将.scss / .css / .html分别存储在数据库中-运行服务器端gulp任务并编译模块并延迟加载它们(然后支持shadow-dom,没有安全问题,还有很多通用性)。
在任何情况下,都有很多理由说明为什么将样式(通过注入或其他方式)放入模板中是一种不良做法,包括违反封装等。
以这种方式应用的样式是全局应用的样式。与使用keepStyle
管道或[attr.style]
相比,这可能是有利的,因为它允许使用角度计算的样式表,如果在库之外使用!important
,则可以使用style
在外部进行覆盖。直接应用于<style>
属性的样式不能被外部CSS覆盖。
无论如何,除了前言之外,您还可以通过将<svg>
标记放置在<svg>
<style>
.global-style-x {
transform: rotate({{someAngleComputation}}deg);
}
</style>
</svg>
<button class="global-style-x">
</button>
标记中来防止其被移除,例如:
[innerHTML]='styleTag | keepHtml"
同样,这些在模板中插入样式的方法都不是最佳实践。
[attr.style]="style | keepStyle"
)。 @ZachDahl和@JuliaPassynkova解决方案,无论是否使用[innerHTML]="yourStyleTag | keepHTML"
或{{1}}之类的管道-...都绕过安全设备,并可能造成注入攻击的威胁。
答案 3 :(得分:0)
样式元素应该在HEAD中。
您可以使用[attr.style]
将样式从字符串应用于html元素 @Component({
selector: 'my-app',
template: `
<div>
<h2 [attr.style]="style">Hello {{name}}</h2>
</div>
`,
})
export class App {
style;
myStyleStr = 'color:blue';
name:string;
constructor(private sanitizer: DomSanitizer) {
this.name = `Angular! v${VERSION.full}`;
this.style = sanitizer.bypassSecurityTrustStyle(this.myStyleStr);
}
}