我正在编写Angular应用程序,并且要显示HTML响应。

我该怎么做?如果我只是简单地使用绑定语法{{myVal}},它会编码所有HTML字符(当然)。

我需要某种方式将innerHTMLdiv绑定到变量值。

评论

有关使组件中定义的CSS在HTML绑定中正确运行的相关文章stackoverflow.com/questions/36265026/…

#1 楼

正确的语法如下:
 <div [innerHTML]="theHtmlString"></div>
 

文档参考

评论


有什么方法可以强制angular在该innerHTML的元素上运行其绑定?我需要使用 ,并希望从外部html提供它。

– thouliha
16年4月29日在22:04

@thouliha我建议您开始撰写有关您问题的新文章。

– prolink007
16年6月20日在20:35

在我的情况下,它呈现字符串,但对标记有所帮助。似乎已经剥离了标记上的属性。我在2.4.6

–crthompson
17 Mar 20 '17在23:10



其他答案stackoverflow.com/a/41089093/1225421和stackoverflow.com/a/41121006/1225421解决了安全HTML sanitzer问题。

– Alex Pandrea
19-4-8在13:35



@jgritten看看npmjs.com/package/ngx-dynamic-hooks

–雷诺(J. Reynolds)
8月31日12:30

#2 楼

Angular 2.0.0和Angular 4.0.0 final



为了安全起见,

 <div [innerHTML]="myVal"></div>
 


DOMSanitizer

需要使用Angulars DOM sanitizer将潜在的不安全HTML明确标记为受信任,因此不会剥离内容的潜在不安全部分

 <div [innerHTML]="myVal | safeHtml"></div>
 


带有类似
的管道

 @Pipe({name: 'safeHtml'})
export class Safe {
  constructor(private sanitizer:DomSanitizer){}

  transform(style) {
    return this.sanitizer.bypassSecurityTrustHtml(style);
    //return this.sanitizer.bypassSecurityTrustStyle(style);
    // return this.sanitizer.bypassSecurityTrustXxx(style); - see docs
  }
}
 


另请参阅在RC.1中,无法使用绑定语法添加某些样式

和文档:https:/ /angular.io/api/platform-b​​rowser/DomSanitizer

安全警告

信任用户添加的HTML可能会带来安全风险。前面提到的文档状态:


调用任何bypassSecurityTrust... API都会禁用Angular对传入值的内置清理。请仔细检查和审核进入此调用的所有值和代码路径。确保为此安全上下文适当地转义了所有用户数据。有关更多详细信息,请参见《安全指南》。


角度标记

类似

 class FooComponent {
  bar = 'bar';
  foo = `<div>{{bar}}</div>
    <my-comp></my-comp>
    <input [(ngModel)]="bar">`;
 




 <div [innerHTML]="foo"></div>
 


不会导致Angular在foo中处理任何特定于Angular的内容。
Angular在生成时用生成的代码替换Angular特定的标记。 Angular不会处理在运行时添加的标记。

要添加包含Angular特定标记(属性或值绑定,组件,指令,管道等)的HTML,需要添加动态模块并在运行时编译组件。
此答案提供了更多详细信息。如何使用/创建动态模板以使用Angular 2.0编译动态组件?

评论


这应该是答案。注意注释掉的两行。实际上,它是处理HTML的第二个。

–crthompson
17 Mar 20 '17在23:28



确保从“ @ angular / platform-b​​rowser”导入{BrowserModule,DomSanitizer}

–crthompson
17 Mar 20 '17在23:29

还要从“ @ angular / core”导入{Pipe}

–Appulus
17 Mar 30 '17 at 9:37

改用DomSanitizer

–GünterZöchbauer
17年7月16日在9:31

这个答案解决了HTML生成的不安全问题。我设法定义了文字颜色,并为其添加了YouTube iframe。您不能像其他答案中那样简单地设置innerHTML来实现此目的。

– Alex Pandrea
19-4-8在13:31



#3 楼

在大多数情况下,[innerHtml]是一个不错的选择,但是在很大的字符串或需要用html进行硬编码的样式时,它会失败。

我想分享其他方法:

您需要做的就是在html文件中创建一个div并为其指定一些ID:

<div #dataContainer></div>


然后在Angular 2组件中创建对此的引用对象(此处为TypeScript):

 import { Component, ViewChild, ElementRef } from '@angular/core';

@Component({
    templateUrl: "some html file"
})
export class MainPageComponent {

    @ViewChild('dataContainer') dataContainer: ElementRef;

    loadData(data) {
        this.dataContainer.nativeElement.innerHTML = data;
    }
}
 


然后只需使用loadData函数将一些文本附加到html元素。

这只是使用本机javascript的一种方法,但是在Angular环境中。我不建议这样做,因为它会使代码更加混乱,但有时没有其他选择。

另请参阅Angular 2-innerHTML样式

评论


其他解决方案首先将字符串保存到html属性,然后再加载html。将大字符串保存到属性会导致浏览器冻结甚至崩溃。我的解决方案省略了这个“属性部分”

– Piotrek
16年8月8日在10:36



是的,否则我不会在这里添加答案

– Piotrek
16年8月8日在10:47

[innerHtml]删除在HTML中硬编码的样式。为了集成所见即所得的编辑器,我必须使用此处列出的方法。

–乔尼·亚当特
16年8月14日在6:11

这对于生成将在HTML电子邮件中生成的内容很有用,但不幸的是仍需要内联样式。其他使用插值的方法删除了内联样式。

–坦率
16年8月31日在17:35

这个@ViewChild可以用于多个div吗?如果是这样,怎么办?

–古兰经
17-2-22在12:07



#4 楼

在angular2@2.0.0-alpha.44上:

当使用{{interpolation}}时,HTML绑定将不起作用,而应使用“表达式”:

无效

 <p [innerHTML]="{{item.anleser}}"></p>
 


->引发错误(插值而不是期望的表达式)

正确

 <p [innerHTML]="item.anleser"></p>
 


->这是正确的方法。

您可以在表达式中添加其他元素,例如:

 <p [innerHTML]="'<b>'+item.anleser+'</b>'"></p>
 


提示

使用[innerHTML]添加的HTML(或通过element.appenChild()等类似方式动态添加的HTML)将不会被Angular处理,除非出于安全目的进行了清理。静态地添加到组件模板。如果需要,可以在运行时创建组件,如我如何使用/创建动态模板以使用Angular 2.0编译动态组件中所述。

评论


第三个示例不起作用。该表达式不求值。输出只是字符串...以其他方式将trustHTML与另一个标签元素组合在一起吗?

–KévinVilela Pinto
16 Dec 6'在8:41

#5 楼

如果其中包含用户创建的内容,则不选择不使用Angular的DOM sanitizer而不直接使用[innerHTML]。 @GünterZöchbauer在他的回答中建议的safeHtml管道是对内容进行消毒的一种方法。以下指令是另一个指令:

 import { Directive, ElementRef, Input, OnChanges, Sanitizer, SecurityContext,
  SimpleChanges } from '@angular/core';

// Sets the element's innerHTML to a sanitized version of [safeHtml]
@Directive({ selector: '[safeHtml]' })
export class HtmlDirective implements OnChanges {
  @Input() safeHtml: string;

  constructor(private elementRef: ElementRef, private sanitizer: Sanitizer) {}

  ngOnChanges(changes: SimpleChanges): any {
    if ('safeHtml' in changes) {
      this.elementRef.nativeElement.innerHTML =
        this.sanitizer.sanitize(SecurityContext.HTML, this.safeHtml);
    }
  }
}
 


要使用

 <div [safeHtml]="myVal"></div>
 


评论


@ObasiObenyOj如果情况有限,您仍然可以在不使用单独指令的情况下执行此操作,构造函数(private sanitizer:Sanitizer){}并将结果绑定到您需要的任何内容中,强烈建议不要使用ElementRef。

– Valex
17年2月3日,11:58

#6 楼


请参考其他最新的答案。


此功能对我有用:<div innerHTML = "{{ myVal }}"></div>(Angular2,Alpha 33)

根据另一种SO:用angular2将服务器中的HTML插入DOM(Angular2中的一般DOM操作),“ inner-html”等效于Angular 1.X中的“ ng-bind-html”。

评论


使用[属性]绑定语法代替{{interpolation}}

–超级照明
17-10-27在9:29

#7 楼

如果在这里我遗漏了一点,我深表歉意,但是我想推荐一种不同的方法:

我认为最好从服务器端应用程序返回原始数据并将其绑定到客户端的模板上侧。由于您只从服务器返回json,因此请求更为灵活。

对我来说,如果您要做的只是从服务器中获取html并将其“按原样”注入DOM中,那么使用Angular似乎并不有意义。

我知道Angular 1.x具有html绑定,但是我还没有看到Angular 2.0中的对应对象。他们可能稍后再添加。无论如何,我仍然会为您的Angular 2.0应用程序考虑一个数据api。

如果您感兴趣的话,这里有一些带有简单数据绑定的示例:http://www.syntaxsuccess.com/viewarticle /angular-2.0-examples

评论


在某些情况下,您肯定希望获取并显示原始html。例如。从远程获取格式化的文章。

–亚历山大·陈(Alexander Chen)
15年12月24日在2:17

另一个经常被忽略的场景是保护模板中的业务逻辑,有时您不希望未经授权的用户看到用于显示信息的逻辑,因此您宁愿在服务器端准备视图

–阿依什(Ayyash)
16-2-20在11:45

另外,显示HTML电子邮件,例如-公平点/问题!

–亲爱的
17年2月6日在9:00



如果您错过了要点(您似乎是自己承认),那么为什么要发表答复?显然,Angular的要点是使用其视图引擎来绑定和呈现数据。但是考虑到有无数的应用程序可以使用Angular应用程序这一事实,实际上可行的是,其中一个或两个应用程序可能要求某些需要在应用程序中显示的数据可能已经被格式化为HTML,开发人员无法控制该内容可能只是这种情况。换句话说...相关问题。

–格雷戈
17年11月1日下午5:50

#8 楼

仅作一个完整的答案,如果您的html内容位于组件变量中,则还可以使用:

<div [innerHTML]=componementVariableThatHasTheHtml></div>


#9 楼

这里已经提供了简短的答案:使用<div [innerHTML]="yourHtml">绑定。

但是这里提到的其他建议可能会引起误解。当您绑定到诸如此类的属性时,Angular具有内置的清理机制。由于Angular不是专用的消毒库,因此对可疑内容过分热衷而不承担任何风险。例如,它将所有SVG内容清除为空字符串。

您可能会听到一些建议,可以通过使用DomSanitizer使用bypassSecurityTrustXXX方法将内容标记为安全来“清除”您的内容。也有人建议使用管道来执行此操作,该管道通常称为safeHtml。所有这些都具有误导性,因为它实际上绕过了清理而不是清理内容。这可能是出于安全考虑,因为如果您对用户提供的内容或不确定的任何内容执行此操作,则可能会遭受恶意代码攻击。

如果Angular删除了您所内置的清理功能是您需要的-可以禁用它,而不是禁用它,而是将实际的清理操作委派给擅长该任务的专用库。例如-DOMPurify。

我为此做了一个包装库,以便可以轻松地与Angular一起使用:
https://github.com/TinkoffCreditSystems/ng-dompurify

它还有一个管道来声明性地清理HTML:

 <div [innerHtml]="value | dompurify"></div>
 


这里建议的管道的不同之处在于,它实际上是通过DOMPurify进行清理的,因此适用于SVG。

要记住的一件事是,DOMPurify非常适合清理HTML / SVG,而不是CSS。因此,您可以提供Angular的CSS清理程序来处理CSS:

 import {NgModule, ɵ_sanitizeStyle} from '@angular/core';
import {SANITIZE_STYLE} from '@tinkoff/ng-dompurify';

@NgModule({
    // ...
    providers: [
        {
            provide: SANITIZE_STYLE,
            useValue: ɵ_sanitizeStyle,
        },
    ],
    // ...
})
export class AppModule {}
 


它是内部的-前缀ɵ,但这就是Angular团队无论如何也要在自己的程序包中使用它的方式。该库还适用于Angular Universal和服务器端优化环境。

#10 楼

只需在HTML中使用[innerHTML]属性即可,如下所示: >您需要在模板中显示的实体?传统的
插补将不起作用,但是innerHTML属性绑定将为您提供帮助。


使用{{myVal}}不能按预期工作!这不会像<p><strong>等HTML标记一样仅将其作为字符串传递...

想象一下您的组件中有以下代码:

const myVal:string ='<strong>Stackoverflow</strong> is <em>helpful!</em>'

如果使用{{myVal}},则会在视图中得到此结果:

<div [innerHTML]="myVal"></div>


,但是使用[innerHTML]="myVal"可以得到预期的结果,如下所示:

Stackoverflow很有帮助!

#11 楼




  <div [innerHTML]="HtmlPrint"></div><br> 





innerHtml是HTML元素的属性,可让您以编程方式设置其html内容。还有一个innerText属性,用于将内容定义为纯文本。

包围属性的方括号定义了Angular输入绑定。这意味着,属性的值(在您的情况下为innerHtml)绑定到给定的表达式,当表达式结果更改时,属性值也更改。

所以基本上[attributeName]="value"允许您绑定并动态更改给定HTML元素的html-conent。

#12 楼

在Angular 2中,您可以执行3种类型的绑定:



[property]="expression"->任何html属性都可以链接到
表达式。在这种情况下,如果expression changes属性将更新,
但是反之亦然。

(event)="expression"->事件激活时执行表达式。

[(ngModel)]="property"->将属性从js(或ts)绑定到html。此属性的任何更新都将在任何地方引起注意。

表达式可以是值,属性或方法。例如:“ 4”,“ controller.var”,“ getValue()”

此处示例

#13 楼

您可以在.html

<div [innerHTML]="announcementContent | safeUrl| safeHtml">
                    </div>


和.ts管道中将多个管道用于样式,链接和HTML,并在.ts管道中使用“ URL”消毒器

import { Component, Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

@Pipe({ name: 'safeUrl' })
export class SafeUrlPipe implements PipeTransform {
    constructor(private sanitizer: DomSanitizer) {}
    transform(url) {
        return this.sanitizer.bypassSecurityTrustResourceUrl(url);
    }
}


用于“ HTML”消毒液的管道

import { Component, Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

@Pipe({
    name: 'safeHtml'
})
export class SafeHtmlPipe implements PipeTransform {
    constructor(private sanitized: DomSanitizer) {}
    transform(value) {
        return this.sanitized.bypassSecurityTrustHtml(value);
    }
}


这将在不影响任何样式和链接单击事件的情况下适用

#14 楼

您还可以使用DOM属性绑定将角度组件类属性与模板绑定。
示例:<div [innerHTML]="theHtmlString"></div>
使用如下所示的规范形式:
<div bind-innerHTML="theHtmlString"></div>

在此处查看有效的stackblitz示例

#15 楼

如Angular 2文档中所述,将元素动态添加到DOM的方法是使用@ Angular / core中的ViewContainerRef类。

要做的是声明一个将实现ViewContainerRef和充当DOM上的占位符。

指令

import { Directive, ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[appInject]'
})
export class InjectDirective {

  constructor(public viewContainerRef: ViewContainerRef) { }

}


然后,在要注入组件的模板中:

HTML

<div class="where_you_want_to_inject">    
  <ng-template appInject></ng-template>
</div>


然后,从注入的组件代码中,您将注入包含所需HTML的组件:

import { Component, OnInit, ViewChild, ComponentFactoryResolver } from '@angular/core';
import { InjectDirective } from '../inject.directive';
import { InjectedComponent } from '../injected/injected.component';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {

  @ViewChild(InjectDirective) injectComp: InjectDirective;

  constructor(private _componentFactoryResolver: ComponentFactoryResolver) {
  }

  ngOnInit() {
  }

  public addComp() {
    const componentFactory = this._componentFactoryResolver.resolveComponentFactory(InjectedComponent);
    const viewContainerRef = this.injectComp.viewContainerRef;
    const componentRef = viewContainerRef.createComponent(componentFactory);
  }

  public removeComp() {
    const componentFactory = this._componentFactoryResolver.resolveComponentFactory(InjectedComponent);
    const viewContainerRef = this.injectComp.viewContainerRef;
    const componentRef = viewContainerRef.remove();
  }

}


我在Angular 2上添加了一个完全可用的演示应用程序,将组件动态添加到DOM演示中

#16 楼

您可以使用多种方法来实现该解决方案。如已批准的答案中所述,您可以使用:

<div [innerHTML]="myVal"></div>


根据您要实现的目标,还可以尝试其他事情,例如javascript DOM(不推荐) ,DOM操作很慢):

演示文稿

<div id="test"></test>


组件

var p = document.getElementsById("test");
p.outerHTML = myVal;


属性绑定

JavaScript DOM外部HTML

评论


不管DOM操作是否比角度操作都慢,使用getElementsById或任何其他选择方法进行操作都是不好的,因为如果它们包含具有相同id(或其他条件)的元素,则它可能捕获属于完全不同的组件的元素。

– Aviad P.
19年2月26日在12:57

另外,它完全可以在任何角度区域之外执行,因此不会发生变化。

–菲利普·迈斯纳(Philipp Meissner)
19年6月13日在10:05

#17 楼

我们始终可以将html内容传递给innerHTML属性,以呈现html动态内容,但是该动态html内容也可以被感染或恶意感染。因此,在将动态内容传递给innerHTML之前,我们应该始终确保对内容进行清理(使用DOMSanitizer),以便我们可以转义所有恶意内容。

请尝试在以下管道中:

import { Pipe, PipeTransform } from "@angular/core";
import { DomSanitizer } from "@angular/platform-browser";

@Pipe({name: 'safeHtml'})
export class SafeHtmlPipe implements PipeTransform {
    constructor(private sanitized: DomSanitizer) {
    }
    transform(value: string) {
        return this.sanitized.bypassSecurityTrustHtml(value);
    }
}

Usage:
<div [innerHTML]="content | safeHtml"></div>


#18 楼

如果您想在Angular 2或Angular 4中使用它,并且还希望保留内联CSS,则可以使用

<div [innerHTML]="theHtmlString | keepHtml"></div>


评论


这给了我一个错误`未捕获(承诺):错误:模板解析错误:找不到管道'keepHtml'。

–普拉文
19年8月28日在9:15

从“ @ angular / core”导入{Pipe,PipeTransform};

– Jay Momaya
19-09-19在12:18

#19 楼

在Angular v2.1.1中工作

<div [innerHTML]="variable or htmlString">
</div>


评论


这将为我生成:
。 div为空。

–斯科特·马库斯(Scott Marcus)
16-11-23在15:54

#20 楼

只是在到目前为止的所有出色答案中添加一些补充:如果您正在使用[innerHTML]渲染Angular组件并且感到它像我一样无法正常工作,请查看我为解决此问题而编写的ngx-dynamic-hooks库非常问题。
使用它,您可以从动态字符串/ html加载组件,而不会影响安全性。它实际上也使用了Angular的DOMSanitizer,就像[innerHTML]一样,但是保留了加载组件的能力(以一种安全的方式)。
在此Stackblitz中进行实际操作。

#21 楼

您可以使用以下两种方式。
<div [innerHTML]="myVal"></div>


<div innerHTML="{{myVal}}"></div>


#22 楼

如果您在有角度的(或任何框架)应用程序中有模板,并且通过HTTP请求/响应从后端返回HTML模板,则您在前端和后端之间混淆了模板。

为什么不仅将模板化的东西留在前端(我建议这样做)还是在后端(相当不透明的imo)?

如果您将模板保留在前端,为什么不只用JSON响应向后端的请求。您甚至不必实现RESTful结构,但是将模板放在一侧可以使您的代码更加透明。

当其他人不得不处理您的代码时(甚至您自己就是这样),这将有所回报。一段时间后重新输入您自己的代码)!

如果操作正确,您将拥有带有小型模板的小组件,而最重要的是,如果您的代码是imba,那么有人不会知道编码语言将能够理解您的模板和逻辑!因此,另外,使您的函数/方法尽可能的小。
您最终会发现,与大型函数/方法/类相比,维护,重构,检查和添加功能要容易得多,并且混淆了模板和逻辑在前端和后端之间-如果您的前端需要更灵活(例如,编写android前端或切换到其他前端框架),请在后端中保留尽可能多的逻辑。

哲学, man :)

ps:您不必实现100%干净的代码,因为它非常昂贵-特别是如果您必须激励团队成员;)
但是:您应该找到一个在更干净的代码方法和所拥有的方法之间取得良好的平衡(也许已经很干净了)

如果可以,请检查该书,并让它进入您的灵魂:
https:// de .wikipedia.org / wiki / Clean_Code

评论


-2票。哈哈好吧,我将投票给这个答案,只是因为很明显其他答案几乎相同。尽管此答案不能提供干净的解决方案,但它只是答案,它使您处于思考状态,而不是复制粘贴某人的解决方案。____在我的情况下,我无法使用此解决方案,因为我在后端有库可以返回代码我必须将其显示为内部html。如果我必须从该库中移走所有内容,则可能要花我一两个星期的时间。有时是不可能的。但是也许我只会在客户端移动样式,这可能会解决我的问题,也可能无法解决。

– makkasi
12月1日18:44