Angular 2 - innerHTML样式

时间:2016-03-28 15:04:23

标签: angular innerhtml

我从HTTP调用中获取大量HTML代码。我将HTML块放在一个变量中并使用[innerHTML]将其插入到我的页面中,但我无法设置插入的HTML块的样式。有没有人有任何建议我怎么做到这一点?

 
lme4

我想要设置样式的HTML是变量" calendar"中包含的块。

11 个答案:

答案 0 :(得分:257)

更新2 ::slotted

所有新浏览器现在都支持

::slotted,并且可以与`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中,以模拟shadow DOM CSS封装,以防止组件内外流失的样式。 Angular还会重写您添加的CSS以匹配这些添加的类。对于使用[innerHTML]添加的HTML,不会添加这些类,并且重写的CSS不匹配。

作为解决方法尝试

  • for CSS添加到组件
/* :host /deep/ mySelector { */
:host ::ng-deep mySelector { 
  background-color: blue;
}
  • for CSS已添加到index.html
/* body /deep/ mySelector { */
body ::ng-deep mySelector {
  background-color: green;
}

>>>(等效/deep//deep/在SASS方面效果更好),::shadow在2.0.0-beta.10中添加。它们类似于shadow DOM CSS组合器(不推荐使用),只能与encapsulation: ViewEncapsulation.Emulated一起使用,这是Angular2中的默认设置。它们可能也与ViewEncapsulation.None一起使用,但之后只会被忽略,因为它们不是必需的。 在支持跨组件样式的更高级功能之前,这些组合器只是一种中间解决方案。

另一种方法是使用

@Component({
  ...
  encapsulation: ViewEncapsulation.None,
})

阻止CSS的所有组件(取决于您添加CSS的位置以及要设置样式的HTML的位置 - 可能是应用程序中的所有组件)

<强>更新

Example Plunker

答案 1 :(得分:4)

您需要遵循的简单解决方案是

transformYourHtml(htmlTextWithStyle) {
    return this.sanitizer.bypassSecurityTrustHtml(html);
  }

答案 2 :(得分:2)

我们经常以[innerHTML]="content.title"的身份从CMS中提取内容。我们将必要的类放置在应用程序的根styles.scss文件中,而不是组件的scss文件中。我们的CMS特意去除了内联样式,因此我们必须准备好准备好供作者在其内容中使用的类。请记住,在模板中使用{{content.title}}不会从内容中呈现html。

答案 3 :(得分:0)

如果您试图在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时,此解决方案可能会遇到问题(尽管更新此解决方案可能会在这种情况下是微不足道的。

答案 4 :(得分:0)

如果您将sass用作样式预处理器,则可以通过以下方式切换回本机Sass编译器以获取开发依赖:

npm install node-sass --save-dev

以便您可以继续使用/ deep /进行开发。

答案 5 :(得分:0)

GünterZö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>'

答案 6 :(得分:0)

对于任何想要将某种样式应用于 innerHTML 的人:

关注Create a safe HTML pipe

您可以使用 CSS 样式连接 HTML 字符串,如下所示:

return this.sanitizer.bypassSecurityTrustHtml(value+='<style type="text/css">.image img { width: 100% }</style>');

这个 value 来自 transform(value, ...args)

答案 7 :(得分:0)

我最初采用 this.sanitizer.bypassSecurityTrustHtml() 路线,并将封装设置为 ViewEncapsulation.NONE,但有两个问题:

  1. ViewEncapsulation.NONE 导致我的组件出现其他样式问题
  2. 我的“安全”html 似乎不适用于 css 变量,即 var(--blue)

这对我有用(无需更改任何其他内容): InsertAdjacentHTML

模板:

<div id=template></div>

代码:

ngOnInit() {
  const el = document.getElementById('template');
  el.insertAdjacentHTML('afterbegin', `<span style="color: var(--blue)">hello</span>`);
}

免责声明:就我而言,我是从配置文件中解析 html 的。您不想使用用户输入的 html 走这条路线。

答案 8 :(得分:0)

最简单直接的方法是使用位于 angular 项目 src 文件夹中的全局样式文件。

假设组件选择器是:app-my-component

在 app-my-component 模板中为承载 innerHtml 内容的元素添加一个类:

<div class="innerhtml-class" [innerHTML]="variable.innerHtml"></div>

添加到全局样式文件:

app-my-component { 
 .innerhtml-class { 
   declaration goes here 
 } 
}

答案 9 :(得分:0)

使用以下方法允许 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

答案 10 :(得分:0)

如果您的动态样式有限,则使用 inline CSS variables 是一种替代解决方案。

// 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);
}