ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

获取组件中定义的 CSS 以在 HTML 绑定中正常工作的相关文章stackoverflow.com/questions/36265026/…

E
Edric

正确的语法如下:

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

Documentation Reference


有什么方法可以强制 angular 对该 innerHTML 的元素运行其绑定?我需要使用 ,并希望从外部 html 提供它。
它在我的情况下呈现字符串,但对标记做了一些事情。似乎已经剥离了标记上的属性。我在 2.4.6
@thouliha 你有没有找到答案?有什么方法可以强制 Angular 在注射后重新评估绑定?我所有的绑定和模板都在 innerHtml 部分中被破坏
其他答案 stackoverflow.com/a/41089093/1225421stackoverflow.com/a/41121006/1225421 解决了安全 HTML sanitzer 问题。
G
Günter Zöchbauer

Angular 2.0.0 和 Angular 4.0.0 最终版

只是为了安全的内容

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

DOMSanitizer

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

<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
  }
}

另请参阅In RC.1 some styles can't be added using binding syntax

和文档:https://angular.io/api/platform-browser/DomSanitizer

安全警告

信任用户添加的 HTML 可能会带来安全风险。 mentioned docs 之前的状态:

调用任何 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,需要添加动态模块并在运行时编译组件。此答案提供了更多详细信息How can I use/create dynamic template to compile dynamic Component with Angular 2.0?


这应该是答案。注意被注释掉的两行。它实际上是处理 HTML 的第二个。
请务必import { BrowserModule, DomSanitizer } from '@angular/platform-browser'
还有import { Pipe } from '@angular/core'
请改用 DomSanitizer
这个答案解决了 HTML 认为不安全产生的问题。我设法定义了文本颜色并用它添加了一个 youtube iframe。您无法通过像其他答案中描述的那样简单地设置 innerHTML 来实现这一点。
G
Günter Zöchbauer

[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 styling


其他解决方案首先将字符串保存到 html 属性,而不是加载 html。将大字符串保存到属性会导致浏览器冻结甚至崩溃。我的解决方案省略了这个“属性部分”
是的,否则我不会在这里添加我的答案
[innerHtml] 删除 Html 中硬编码的样式。为了集成所见即所得的编辑器,我不得不使用此处列出的方法。
这对于生成将进入 HTML 电子邮件的内容非常有用,不幸的是,仍然需要内联样式。其他使用插值的方法删除了内联样式。
这个 @ViewChild 可以用于多个 div 吗?如果是这样,如何?
j
jvoigt

在 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>

暗示

Angular 不会以任何方式处理使用 [innerHTML] 添加的 HTML(或通过 element.appenChild() 或类似方式动态添加的 HTML),除非出于安全目的进行清理。
只有当 HTML 静态添加到一个组件模板。如果需要,您可以在运行时创建一个组件,如 How can I use/create dynamic template to compile dynamic Component with Angular 2.0? 中所述


第三个例子不起作用。表达式不求值。输出只是字符串......还有其他方法可以将trustedHTML 与另一个标签元素结合起来吗?
C
Community

如果 [innerHTML] 包含用户创建的内容,则不能直接使用 [innerHTML] 而不使用 Angular 的 DOM sanitizer。 @GünterZöchbauer in his answer 建议的 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 如果是有限的情况,您仍然可以在不使用单独指令的情况下执行此操作,constructor( private sanitizer: Sanitizer) {} 并将结果绑定到您需要的任何内容中,强烈建议不要使用 ElementRef。
它是否适用于输入和文本区域元素?
F
Fan Li

请参阅其他更新的答案。

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

根据另一个 SO:Inserting HTML from server into DOM with angular2 (general DOM manipulation in Angular2),“inner-html”相当于 Angular 1.X 中的“ng-bind-html”


使用 [property] 绑定语法而不是 {{interpolation}}
也可以在我无法工作的项目中工作
S
Serj Sagan

为了获得完整的答案,如果您的 HTML 内容在 component variable 中,您还可以使用:

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

T
TGH

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

我认为最好从服务器端应用程序返回原始数据并将其绑定到客户端的模板。这使得请求更加灵活,因为您只从服务器返回 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 的用例。例如,从远程获取格式化的文章。
另一个经常被忽略的场景是保护模板中的业务逻辑,您有时不希望未经授权的用户看到您用于显示信息的逻辑,因此您宁愿在服务器端准备视图
如果您错过了重点(您似乎自己承认),那么为什么要发布回复?显然,Angular 的重点是使用它的视图引擎来绑定和渲染数据。但考虑到可能使用 Angular 应用程序的应用程序不计其数,实际上可行的是,其中一两个应用程序可能需要一些需要在应用程序中显示的数据可能已经格式化为 HTML,并且可能恰好是开发人员无法控制该内容的情况。换句话说......相关问题。
w
waterplea

此处已提供简短答案:使用 <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 sanitizer 来处理 CSS:

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

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

它是内部的——hense ɵ 前缀,但这也是 Angular 团队在他们自己的包中使用它的方式。该库也适用于 Angular Universal 和服务器端渲染环境。


A
Alireza

只需在 HTML 中使用 [innerHTML] 属性,如下所示:

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

您的组件中是否曾经有包含一些 html 标记或需要在模板中显示的实体的属性?传统的插值不起作用,但 innerHTML 属性绑定来拯救。

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

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

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

如果您使用 {{myVal}},您将在视图中看到:

<strong>Stackoverflow</strong> is <em>helpful!</em>

但使用 [innerHTML]="myVal" 会产生预期的结果,如下所示:

Stackoverflow 很有帮助!


H
Hitech Hitesh


innerHtml 是 HTML-Elements 的一个属性,它允许您以编程方式设置它的 html 内容。还有一个 innerText 属性将内容定义为纯文本。

围绕属性的 [attributeName]="value" 方括号定义了 Angular 输入绑定。这意味着,属性的值(在您的情况下为 innerHtml)绑定到给定的表达式,当表达式结果发生变化时,属性值也会发生变化。

所以基本上 [innerHtml] 允许您绑定和动态更改给定 HTML 元素的 html 内容。


S
Sahil Ralkar

您可以在 .html 中为样式、链接和 HTML 应用多个管道,如下所示

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

并在 .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);
    }
}

这将同时适用而不会干扰任何样式和链接点击事件


C
Community

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

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

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

[(ngModel)]="property" -> 将属性从 js(或 ts)绑定到 html。此属性的任何更新都会随处可见。

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

示例 here


J
Jasdeep Singh

您还可以使用 DOM 属性绑定将角度组件类属性与模板绑定。

示例:<div [innerHTML]="theHtmlString"></div>

使用如下规范形式:

<div bind-innerHTML="theHtmlString"></div>

角度文档:https://angular.io/guide/template-syntax#property-binding-property

查看工作中的 stackblitz example here


S
Suneet Bansal

我们始终可以将 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>

H
Hasee Amarathunga

您可以使用以下两种方式。

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

或者

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

T
Tharindu Lakshan

Angular 2+ 支持将呈现 HTML 的 [innerHTML] 属性绑定。如果您要以其他方式使用插值,它将被视为字符串。

进入 .html 文件

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

进入 .ts 文件

theHtmlString:String = "enter your html codes here";

J
Josef

我已经构建了下面的库,这将有助于重新绑定 html 格式的绑定。请找到以下步骤来使用这个库。这个库基本上允许在 AOT 中注入 JIT 编译器代码

使用 npm i angular-html-recompile 安装库 在 app.component.html 文件中添加以下代码 在 app.component.ts 文件中使用下面的代码 import { Component, OnInit, ViewChild } from '@angular/core';从 'angular-html-recompile' 导入 { AngularHtmlRecompileComponent, AngularHtmlRecompileService }; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) 导出类 AppComponent 实现 OnInit { @ViewChild(AngularHtmlRecompileComponent, { static: true }) comp !: AngularHtmlRecompileComponent;构造函数(私有 angularHtmlRecompileService:AngularHtmlRecompileService){}公共数据对象:任何;公共模板 = `

`; ngOnInit(): void { this.angularHtmlRecompileService.sharedData.subscribe((respose: any) => { if (respose) { switch (respose.key) { case `Username`: // 更改名称时调用任何方法 break; case `Password`: //从主组件更新密码 this.comp[`cmpRef`].instance['Password'] = "Karthik"; break; case `submit`: //在提交点击时获取所有参数的引用 / /1. respose.data OR //使用 this.comp[`cmpRef`].instance break; 默认值:break; } } }); this.prepareData(); } prepareData() { //准备以下格式的数据只是为了方便绑定 //模板准备和数据准备一旦从服务接收到数据就可以完成 // AngularHtmlRecompileComponent 在你传递数据之前不会被渲染 this.dataObject = [ { key: '用户名',值:'Pranay'},{键:'电子邮件',值:'abc@test.com',},{键:'密码',值:'test123',},{键:'角色', value: ['Admin', 'Author', 'Reader'] }, { key: 'isShow', value: this.updateView() } ]; } updateView() { //在渲染到 UI 之前写下逻辑以工作 ngIf 指令 return true; } } 添加模块到 app.module.ts 文件 import { NgModule } from '@angular/core';从“@angular/platform-browser”导入 { BrowserModule };从'./app.component'导入{AppComponent};从“angular-html-recompile”导入{ AngularHtmlRecompileModule }; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AngularHtmlRecompileModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } 这个库支持基本的 html、Angular 材质、flex 布局。要使用此功能,请安装以下依赖项 npm i -s @angular/material @angular/flex-layout


B
BogdanC

如 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 dynamically add component to DOM demo 添加了一个完整的演示应用程序


J
João Beirão

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

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

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

介绍

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

零件

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

Property Binding

Javascript DOM Outer HTML


不管 DOM 操作是否比 Angular 慢,使用 getElementsById 或任何其他选择方法都是不好的,因为如果它们包含具有相同 id(或其他条件)的元素,它可能会捕获属于完全不同组件的元素。
此外,它完全在任何角度区域之外执行,因此不会拾取更改。
J
Jay Momaya

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

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

这给了我一个错误`未捕获(承诺):错误:模板解析错误:找不到管道'keepHtml''
从“@angular/core”导入 {Pipe,PipeTransform};
@JayMomaya 你可能会错过指令 keepHtml
E
Edric

在 Angular v2.1.1 中工作

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

这会为我产生:<div _ngcontent-luf-0=""></div>div 为空。
M
Mvin

只是对迄今为止的所有出色答案发表一点补充:如果您使用 [innerHTML] 呈现 Angular 组件并且对它无法像我一样工作感到沮丧,请查看我为解决此问题而编写的 ngx-dynamic-hooks 库非常有问题。

有了它,您可以从动态字符串/html 加载组件而不会影响安全性。它实际上像 [innerHTML] 一样使用 Angular 的 DOMSanitizer,但保留了加载组件的能力(以安全的方式)。

在行动 in this Stackblitz 中看到它。


G
Guntram

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

为什么不将模板内容留在前端(我建议)或后端(非常不透明的 imo)?

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

当其他人不得不处理您的代码(或者甚至您自己在一段时间后重新输入自己的代码)时,这将得到回报!

如果你做得对,你将拥有带有小模板的小组件,最重要的是,如果你的代码是 imba,那么不懂编码语言的人将能够理解你的模板和逻辑!因此,另外,尽可能地保持你的函数/方法小。您最终会发现,与大型函数/方法/类以及在前端和后端之间混合模板和逻辑相比,维护、重构、审查和添加功能要容易得多 - 并将尽可能多的逻辑保留在后端如果您的前端需要更灵活(例如编写一个 android 前端或切换到不同的前端框架)。

哲学,男人:)

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

如果可以的话,检查一下这本书,让它进入你的灵魂:https://de.wikipedia.org/wiki/Clean_Code


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