Angularアプリケーションを作成していて、表示したいHTML応答があります。
それ、どうやったら出来るの?バインディング構文を使用するだけで、{{myVal}}
すべてのHTML文字が(もちろん)エンコードされます。
どうにかしてinnerHTML
a div
を変数値にバインドする必要があります。
Angularアプリケーションを作成していて、表示したいHTML応答があります。
それ、どうやったら出来るの?バインディング構文を使用するだけで、{{myVal}}
すべてのHTML文字が(もちろん)エンコードされます。
どうにかしてinnerHTML
a div
を変数値にバインドする必要があります。
回答:
Angular 2.0.0およびAngular 4.0.0 final
安全なコンテンツのためだけに
<div [innerHTML]="myVal"></div>
DOMSanitizer
安全でない可能性のあるHTMLは、Angulars DOMサニタイザーを使用して信頼できるものとして明示的にマークする必要があるため、コンテンツの安全でない可能性がある部分を削除しません
<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-browser/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がAngular固有の何かを処理することはありませんfoo
。Angularはビルド時にAngular固有のマークアップを生成されたコードで置き換えます。実行時に追加されたマークアップは、Angularによって処理されません。
Angular固有のマークアップ(プロパティまたは値のバインディング、コンポーネント、ディレクティブ、パイプなど)を含むHTMLを追加するには、動的モジュールを追加し、実行時にコンポーネントをコンパイルする必要があります。この回答は詳細を提供します動的テンプレートを使用/作成して動的コンポーネントをAngular 2.0でコンパイルするにはどうすればよいですか?
import { BrowserModule, DomSanitizer } from '@angular/platform-browser'
import { Pipe } from '@angular/core'
[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スタイリングも参照してください。
nativeElement
直接にのプロパティにアクセスしますが、これは悪い習慣と見なされています。私は間違い[innerHTML]="..."
なく同じことを内部で行いますが、Angular2の良い練習方法です。
[innerHTML]
Angular2 で実際に大きな文字列に問題が発生しましたか?
[innerHtml]
Htmlにハードコーディングされたスタイルを削除します。wysiwygエディターを統合するために、ここにリストされているアプローチを使用する必要がありました。
[innerHTML]
が、アプローチは機能しませんでした。
angular2@2.0.0-alpha.44で:
Html-Bindingはを使用すると機能しません{{interpolation}}
。代わりに「式」を使用してください。
無効
<p [innerHTML]="{{item.anleser}}"></p>
->エラーをスローします(予想される式の代わりに補間)
正しい
<p [innerHTML]="item.anleser"></p>
->これが正しい方法です。
次のように、式に要素を追加できます。
<p [innerHTML]="'<b>'+item.anleser+'</b>'"></p>
ヒント
を使用して追加された[innerHTML]
(またはelement.appenChild()
同様の方法で動的に追加された)HTMLは、セキュリティを目的としたサニタイズ以外の方法では、Angularによって処理されません。
このような機能は、HTMLがコンポーネントテンプレートに静的に追加された場合にのみ機能します。これが必要な場合は、動的テンプレートを使用/作成してAngular 2.0で動的コンポーネントをコンパイルする方法で説明されているように、実行時にコンポーネントを作成できます。
AngularのDOMサニタイザーを使用せずに[innerHTML]を直接使用することは、ユーザーが作成したコンテンツが含まれている場合はオプションではありません。@GünterZöchbauer が彼の回答で提案したsafeHtmlパイプは、コンテンツをサニタイズする1つの方法です。次のディレクティブは別のものです。
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>
Can't bind to 'safeHtml' since it isn't a known property of 'div'.
ng-version 2.4.4が発生します
constructor( private sanitizer: Sanitizer) {}
、結果を必要なものにバインドします。また、ElementRefの使用は強くお勧めしません。
最新の回答を参考にしてください。
これは私にとってはうまくいきます: <div innerHTML = "{{ myVal }}"></div>
うまくいき(Angular2、Alpha 33)
別のSOによると:サーバーからHTMLをangular2(Angular2の一般的なDOM操作)でDOMに挿入すると、「inner-html」はAngular 1.Xの「ng-bind-html」に相当します
ここでポイントが欠けていることをお詫びしますが、別のアプローチをお勧めします。
サーバー側のアプリケーションから生データを返し、それをクライアント側のテンプレートにバインドする方が良いと思います。サーバーからjsonを返すだけなので、これにより軽快なリクエストが増えます。
私からは、サーバーからhtmlをフェッチしてDOMに「そのまま」注入するだけの場合、Angularを使用しても意味がないように思えます。
Angular 1.xにHTMLバインディングがあることは知っていますが、Angular 2.0にはまだ対応していません。彼らは後でそれを追加するかもしれません。とにかく、私はまだあなたのAngular 2.0アプリのデータAPIを検討します。
ここにいくつかのサンプルがあります。興味がある場合は、いくつかの単純なデータバインディングを使用してください。http://www.syntaxsuccess.com/viewarticle/angular-2.0-examples
簡単な答えはすでにここに提供されています:使用 <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には適していません。したがって、CSSを処理するためにAngularの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とサーバー側の再リンク環境でも機能します。
以下のような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は役に立ちます!
.htmlで次のように、スタイル、リンク、HTMLに複数のパイプを適用できます
<div [innerHTML]="announcementContent | safeUrl| safeHtml">
</div>
そして「URL」サニタイザーのための.tsパイプ
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);
}
}
これは、スタイルやリンククリックイベントを妨げることなく適用されます。
<div [innerHTML]="HtmlPrint"></div><br>
innerHTMLのは、あなたがそれをプログラム的にHTMLコンテンツです設定することを可能にするHTML要素のプロパティです。コンテンツをプレーンテキストとして定義するinnerTextプロパティもあります。
[attributeName]="value"
属性を囲むボックスブラケットは、角度入力結合を定義します。つまり、プロパティの値(あなたの場合はinnerHtml)が指定された式にバインドされ、expression-resultが変更されると、プロパティ値も変更されます。
したがって、基本的に[innerHtml]
は、指定されたHTML要素のhtml-conentをバインドして動的に変更することができます。
では角度2あなたは、バインディングの3種類の操作を行うことができます。
[property]="expression"
->任意のhtmlプロパティが(event)="expression"
->イベントがアクティブになると、式が実行されます。[(ngModel)]="property"
->プロパティをjs(またはts)からhtmlにバインドします。このプロパティの更新はどこでも顕著になります。式には、値、属性、またはメソッドを指定できます。例: '4'、 'controller.var'、 'getValue()'
ここの例
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();
}
}
ソリューションを実現するには、いくつかのアプローチを使用できます。承認済みの回答ですでに述べたように、次のものを使用できます。
<div [innerHTML]="myVal"></div>
達成しようとしていることに応じて、JavaScript DOMのような他のことも試すことができます(非推奨、DOM操作は遅い):
プレゼンテーション
<div id="test"></test>
成分
var p = document.getElementsById("test");
p.outerHTML = myVal;
getElementsById
やその他の選択方法を使用してそれを行うと、同じID(または他の基準)の要素が含まれている場合、完全に異なるコンポーネントに属する要素をキャプチャする可能性があるため、不適切です
innerHTML
プロパティにHTMLコンテンツを常に渡して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>
style: background-color
、すべてのものが取り除かれる可能性があるため、最初からこれを使い始めるのが最善です。そうしないと、後で非常に混乱するでしょう。
以下のような正規形を使用して、角度コンポーネントクラスプロパティをテンプレートにバインドすることもできます。
<div bind-innerHTML="theHtmlString"></div>
Angularのドキュメント:https : //angular.io/guide/template-syntax#property-binding-property
Angular v2.1.1での作業
<div [innerHTML]="variable or htmlString">
</div>
<div _ngcontent-luf-0=""></div>
私のために生成 します。div
空です。
アンギュラー(または任意のフレームワーク)アプリケーションにテンプレートがあり、HTTP要求/応答を介してバックエンドからHTMLテンプレートを返す場合、フロントエンドとバックエンドの間でテンプレートを混同しています。
フロントエンド(私はそれをお勧めします)またはバックエンド(かなり不透明なimo)にテンプレートの要素を残さないのはなぜですか?
また、テンプレートをフロントエンドに保持している場合は、JSONで応答してバックエンドへのリクエストを送信しないでください。RESTfulな構造を実装する必要さえありませんが、テンプレートを片側に保持することで、コードがより透過的になります。
これは、他の誰かがあなたのコードに対処しなければならない場合(またはあなた自身がしばらくしてから自分のコードを再入力する場合)に返済します!
正しく実行すれば、小さなテンプレートを備えた小さなコンポーネントができます。何よりも、コードがimbaであれば、コーディング言語を知らない人でもテンプレートとロジックを理解できるでしょう。したがって、さらに、関数/メソッドをできる限り小さくしてください。大規模な関数/メソッド/クラスと比較して、機能の維持、リファクタリング、レビュー、追加が簡単で、フロントエンドとバックエンド間でテンプレートとロジックを混同することが、最終的にわかります。フロントエンドをより柔軟にする必要がある場合(例:androidフロントエンドの作成または別のフロントエンドフレームワークへの切り替え)。
哲学、男:)
PS:100%クリーンなコードを実装する必要はありません。これは非常にコストがかかるためです。特に、チームメンバーのやる気を引き出さなければならない場合はそうです;)しかし:クリーンなコードへのアプローチと現在のもの(たぶんそれ)のバランスをとる必要があります。すでにかなりきれいです)
できれば本をチェックして、それをあなたの心に入れてください:https : //de.wikipedia.org/wiki/Clean_Code