[英]Angular 2 - innerHTML styling
I am getting chunks of HTML codes from HTTP calls.我从 HTTP 调用中获取了大量 HTML 代码。 I put the HTML blocks in a variable and insert it on my page with[innerHTML] but i can not style the inserted HTML block.
我将 HTML 块放在一个变量中,并使用 [innerHTML] 将其插入到我的页面中,但我无法设置插入的 HTML 块的样式。 Does anyone have any suggestion how i might achieve this?
有没有人对我如何实现这一目标有任何建议?
@Component({selector: 'calendar',
template: '<div [innerHTML]="calendar"></div>',
providers:[HomeService],
styles: [`
h3 {color:red;}
`})
The HTML that I want to style is the block contained in the variable "calendar".我想要设置样式的 HTML 是包含在变量“日历”中的块。
update 2 ::slotted
更新 2
::slotted
::slotted
is now supported by all new browsers and can be used with ViewEncapsulation.ShadowDom
::slotted
现在所有新浏览器都支持,并且可以与ViewEncapsulation.ShadowDom
一起使用
https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted
update 1 ::ng-deep更新 1 ::ng-深
/deep/
was deprecated and replaced by ::ng-deep
. /deep/
已被弃用并由::ng-deep
取代。
::ng-deep
is also already marked deprecated, but there is no replacement available yet. ::ng-deep
也已经被标记为已弃用,但目前还没有可用的替代品。
When ViewEncapsulation.Native
is properly supported by all browsers and supports styling accross shadow DOM boundaries, ::ng-deep
will probably be discontinued.当所有浏览器都正确支持
ViewEncapsulation.Native
并支持ViewEncapsulation.Native
阴影 DOM 边界的样式时, ::ng-deep
可能会停止使用。
original原创
Angular adds all kinds of CSS classes to the HTML it adds to the DOM to emulate shadow DOM CSS encapsulation to prevent styles of bleeding in and out of components. Angular 将各种 CSS 类添加到它添加到 DOM 的 HTML 中,以模拟 shadow DOM CSS 封装,以防止样式渗入和渗出组件。 Angular also rewrites the CSS you add to match these added classes.
Angular 还会重写您添加的 CSS 以匹配这些添加的类。 For HTML added using
[innerHTML]
these classes are not added and the rewritten CSS doesn't match.对于使用
[innerHTML]
添加的 HTML,不会添加这些类,并且重写的 CSS 不匹配。
As a workaround try作为解决方法尝试
/* :host /deep/ mySelector { */
:host ::ng-deep mySelector {
background-color: blue;
}
index.html
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. >>>
(和等效的/deep/
但/deep/
在 SASS 中效果更好)和::shadow
是在 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.它们类似于 shadow DOM CSS 组合器(已弃用)并且仅适用于
encapsulation: ViewEncapsulation.Emulated
,这是encapsulation: ViewEncapsulation.Emulated
中的默认值。 They probably also work with ViewEncapsulation.None
but are then only ignored because they are not necessary.它们可能也与
ViewEncapsulation.None
一起ViewEncapsulation.None
但随后只会被忽略,因为它们不是必需的。 These combinators are only an intermediate solution until more advanced features for cross-component styling is supported.在支持跨组件样式的更高级功能之前,这些组合器只是一个中间解决方案。
Another approach is to use另一种方法是使用
@Component({
...
encapsulation: ViewEncapsulation.None,
})
for all components that block your CSS (depends on where you add the CSS and where the HTML is that you want to style - might be all components in your application)对于所有阻止您的 CSS 的组件(取决于您添加 CSS 的位置以及您想要设置样式的 HTML - 可能是您应用程序中的所有组件)
Update更新
The simple solution you need to follow is您需要遵循的简单解决方案是
import { DomSanitizer } from '@angular/platform-browser';
constructor(private sanitizer: DomSanitizer){}
transformYourHtml(htmlTextWithStyle) {
return this.sanitizer.bypassSecurityTrustHtml(htmlTextWithStyle);
}
We pull in content frequently from our CMS as [innerHTML]="content.title"
.我们经常从我们的 CMS 中提取内容作为
[innerHTML]="content.title"
。 We place the necessary classes in the application's root styles.scss
file rather than in the component's scss file.我们将必要的类放在应用程序的根
styles.scss
文件中,而不是放在组件的 scss 文件中。 Our CMS purposely strips out in-line styles so we must have prepared classes that the author can use in their content.我们的 CMS 有意去除内联样式,因此我们必须准备好作者可以在其内容中使用的类。 Remember using
{{content.title}}
in the template will not render html from the content.请记住,在模板中使用
{{content.title}}
不会从内容呈现 html。
If you're trying to style dynamically added HTML elements inside an Angular component, this might be helpful:如果您尝试在 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(), '')
}
My guess is that the convention for this attribute is not guaranteed to be stable between versions of Angular, so that one might run into problems with this solution when upgrading to a new version of Angular (although, updating this solution would likely be trivial in that case).我的猜测是,这个属性的约定不能保证在 Angular 的版本之间是稳定的,因此在升级到新版本的 Angular 时可能会遇到这个解决方案的问题(虽然,更新这个解决方案可能是微不足道的)情况)。
The recommended version by Günter Zöchbauer works fine, but I have an addition to make. Günter Zöchbauer 推荐的版本工作正常,但我有一个补充。 In my case I had an unstyled html-element and I did not know how to style it.
就我而言,我有一个无样式的 html 元素,但我不知道如何设置它的样式。 Therefore I designed a pipe to add styling to it.
因此,我设计了一个管道来为其添加样式。
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);
}
}
Then you can add style to any html-element like this:然后你可以像这样为任何 html 元素添加样式:
<span [innerhtml]="Variable | StyleClass: 'margin': '0'"> </span>
With:与:
Variable = '<p> Test </p>'
For anyone that wants just applies a certain style to innerHTML :对于任何想要将某种样式应用于 innerHTML 的人:
Follow Create a safe HTML pipe 创建一个安全的 HTML 管道
And you can concat your HTML string with CSS style like this:您可以使用 CSS 样式连接您的 HTML 字符串,如下所示:
return this.sanitizer.bypassSecurityTrustHtml(value+='<style type="text/css">.image img { width: 100% }</style>');
This value
is from transform(value, ...args)这个
value
来自 transform(value, ...args)
I went the this.sanitizer.bypassSecurityTrustHtml()
route initially, and set encapsulation to ViewEncapsulation.NONE
, but had 2 problems:我最初使用
this.sanitizer.bypassSecurityTrustHtml()
路由,并将封装设置为ViewEncapsulation.NONE
,但有两个问题:
ViewEncapsulation.NONE
was causing other styling issues in my component ViewEncapsulation.NONE
在我的组件中导致了其他样式问题 This worked for me (without having to change anything else): InsertAdjacentHTML这对我有用(无需更改任何其他内容): InsertAdjacentHTML
Template:模板:
<div id=template></div>
Code:代码:
ngOnInit() {
const el = document.getElementById('template');
el.insertAdjacentHTML('afterbegin', `<span style="color: var(--blue)">hello</span>`);
}
Disclaimer : In my case, I was parsing html from config files.免责声明:就我而言,我是从配置文件中解析 html 的。 You wouldn't want to go this route with user inputted html.
您不想使用用户输入的 html 走这条路线。
The easiest and most straight forward is to use the global styles file located in angular project src folder.最简单、最直接的是使用位于 angular 项目 src 文件夹中的全局样式文件。
Assuming the component selector is: app-my-component假设组件选择器是:app-my-component
Add a class to the element hosting the innerHtml content in app-my-component template:向在 app-my-component 模板中托管 innerHtml 内容的元素添加一个类:
<div class="innerhtml-class" [innerHTML]="variable.innerHtml"></div>
Add to the global styles file:添加到全局样式文件:
app-my-component {
.innerhtml-class {
declaration goes here
}
}
Use the below method to allow CSS styles in innerhtml
.使用以下方法在
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>`);
}
Example code stackblitz示例代码stackblitz
Or use the below method to write directly in HTML.或者使用下面的方法直接在HTML中编写。 https://gist.github.com/klihelp/4dcac910124409fa7bd20f230818c8d1
https://gist.github.com/klihelp/4dcac910124409fa7bd20f230818c8d1
Using inline CSS variables is an alternative solution if you have limited styles that are dynamic.如果您的动态样式有限,则使用内联 CSS 变量是一种替代解决方案。
Ie即
// file.ts
someVarWithHtml = 'Hello <span class="dynamic">World</span>';
// file.ng.html
<div [style]="'--my-var: ' + value"
[innerHTML]="someVarWithHtml"></div>
// style.css
.dynamic {
background: var(--my-var);
}
I am getting chunks of HTML codes from HTTP calls.我从HTTP调用中获取了很多HTML代码。 I put the HTML blocks in a variable and insert it on my page with[innerHTML] but i can not style the inserted HTML block.
我将HTML块放入变量中,然后使用[innerHTML]将其插入到我的页面中,但是无法为插入的HTML块设置样式。 Does anyone have any suggestion how i might achieve this?
有人对我将如何实现这一目标有任何建议吗?
@Component({selector: 'calendar',
template: '<div [innerHTML]="calendar"></div>',
providers:[HomeService],
styles: [`
h3 {color:red;}
`})
The HTML that I want to style is the block contained in the variable "calendar".我要设置样式的HTML是变量“ calendar”中包含的块。
If you are using sass as style preprocessor, you can switch back to native Sass compiler for dev dependency by:如果您使用 sass 作为样式预处理器,您可以通过以下方式切换回本机 Sass 编译器以获取开发依赖项:
npm install node-sass --save-dev
So that you can keep using /deep/ for development.这样您就可以继续使用 /deep/ 进行开发。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.