简体   繁体   English

Angular 2 - innerHTML 样式

[英]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作为解决方法尝试

  • for CSS added to the component用于添加到组件的 CSS
/* :host /deep/ mySelector { */
:host ::ng-deep mySelector { 
  background-color: blue;
}
  • for CSS added to 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更新

Example Plunker示例 Plunker

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 ,但有两个问题:

  1. ViewEncapsulation.NONE was causing other styling issues in my component ViewEncapsulation.NONE在我的组件中导致了其他样式问题
  2. My "safe" html didn't appear to work with css variables, ie var(--blue)我的“安全”html 似乎不适用于 css 变量,即 var(--blue)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM