我从HTTP调用中获得了大量的HTML代码。我把HTML块放在一个变量,并将它插入到我的页面[innerHTML],但我不能样式插入的HTML块。有人有什么建议吗?
@Component({
selector: 'calendar',
template: '<div [innerHTML]="calendar"></div>',
providers: [HomeService],
styles: [`h3 { color: red; }`]
})
我想要样式的HTML是包含在变量“日历”中的块。
更新2::slot
:: slots现在被所有的新浏览器所支持,并且可以和ViewEncapsulation一起使用。ShadowDom
https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted
更新1::ng-deep
/deep/已弃用,并由::ng-deep取代。
::ng-deep也已被标记为已弃用,但目前还没有可用的替代品。
当ViewEncapsulation。Native被所有浏览器正确地支持,并支持跨阴影DOM边界的样式,::ng-deep可能会停止使用。
原始
Angular将各种CSS类添加到它添加到DOM的HTML中,以模拟影子DOM CSS封装,以防止样式流入和流出组件。Angular还会重写你添加的CSS来匹配这些添加的类。对于使用[innerHTML]添加的HTML,这些类没有添加,重写的CSS也不匹配。
作为一个变通的尝试
为CSS添加到组件
/* :host /deep/ mySelector { */
:host ::ng-deep mySelector {
background-color: blue;
}
用于添加到index.html的CSS
/* body /deep/ mySelector { */
body ::ng-deep mySelector {
background-color: green;
}
>>> (and the equivalent/deep/ but /deep/ works better with SASS) and ::shadow were added in 2.0.0-beta.10. They are similar to the shadow DOM CSS combinators (which are deprecated) and only work with encapsulation: ViewEncapsulation.Emulated which is the default in Angular2. They probably also work with ViewEncapsulation.None but are then only ignored because they are not necessary.
These combinators are only an intermediate solution until more advanced features for cross-component styling is supported.
另一种方法是使用
@Component({
...
encapsulation: ViewEncapsulation.None,
})
对于所有阻碍CSS的组件(取决于你添加CSS的位置以及你想要样式化的HTML的位置——可能是你应用程序中的所有组件)
更新
例子恰好
如果你想在Angular组件中动态添加HTML元素,这可能会有帮助:
// inside component class...
constructor(private hostRef: ElementRef) { }
getContentAttr(): string {
const attrs = this.hostRef.nativeElement.attributes
for (let i = 0, l = attrs.length; i < l; i++) {
if (attrs[i].name.startsWith('_nghost-c')) {
return `_ngcontent-c${attrs[i].name.substring(9)}`
}
}
}
ngAfterViewInit() {
// dynamically add HTML element
dynamicallyAddedHtmlElement.setAttribute(this.getContentAttr(), '')
}
我的猜测是,这个属性的约定不能保证在不同版本的Angular之间是稳定的,所以当升级到新版本的Angular时,这个解决方案可能会遇到问题(尽管,在这种情况下,更新这个解决方案可能是微不足道的)。
Günter Zöchbauer推荐的版本很好,但我要做一个补充。在我的例子中,我有一个没有样式的html元素,我不知道如何样式它。因此,我设计了一个管道来添加样式。
import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
@Pipe({
name: 'StyleClass'
})
export class StyleClassPipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer) { }
transform(html: any, styleSelector: any, styleValue: any): SafeHtml {
const style = ` style = "${styleSelector}: ${styleValue};"`;
const indexPosition = html.indexOf('>');
const newHtml = [html.slice(0, indexPosition), style, html.slice(indexPosition)].join('');
return this.sanitizer.bypassSecurityTrustHtml(newHtml);
}
}
然后你可以像这样给任何html元素添加样式:
<span [innerhtml]="Variable | StyleClass: 'margin': '0'"> </span>
:
Variable = '<p> Test </p>'
我最初执行this.sanitizer.bypassSecurityTrustHtml()路由,并将封装设置为ViewEncapsulation。没有,但有两个问题:
ViewEncapsulation。NONE在我的组件中引起了其他样式问题
我的“安全”html似乎不工作与css变量,即var(——蓝色)
这对我来说是有效的(不需要更改任何其他内容):InsertAdjacentHTML
模板:
<div id=template></div>
代码:
ngOnInit() {
const el = document.getElementById('template');
el.insertAdjacentHTML('afterbegin', `<span style="color: var(--blue)">hello</span>`);
}
免责声明:在我的例子中,我是从配置文件中解析html。对于用户输入的html,您不会希望走这条路线。
最简单、最直接的方法是使用angular project src文件夹中的全局样式文件。
假设组件选择器是:app-my-component
在app-my-component模板中,向innerHtml内容所在的元素中添加一个类:
<div class="innerhtml-class" [innerHTML]="variable.innerHtml"></div>
添加到全局样式文件:
app-my-component {
.innerhtml-class {
declaration goes here
}
}
使用下面的方法在innerhtml中允许CSS样式。
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
.
.
.
.
html: SafeHtml;
constructor(protected _sanitizer: DomSanitizer) {
this.html = this._sanitizer.bypassSecurityTrustHtml(`
<html>
<head></head>
<body>
<div style="display:flex; color: blue;">
<div>
<h1>Hello World..!!!!!</h1>
</div>
</div>
</body>
</html>`);
}
示例代码stackblitz
或者使用下面的方法直接在HTML中编写。
https://gist.github.com/klihelp/4dcac910124409fa7bd20f230818c8d1