結論
先に結論を書きます。
タグ属性なしでバインド -> innerHTML 属性にバインド
タグ属性含めてバインド -> DomSanitizer.bypassSecurityTrustHtml()
を使う
1. Angular では HTMLタグがエスケープされてバインドされる
セキュリティの都合で、Angularのバインド機能を使って動的に文字列を表示する際は、必ずエスケープされて表示されます。これがデフォルトの処理となります。
したがって、動的にHTMLデータを表示したくても、HTMLのタグがタグの文字列のまま出力されてしまいます。
import { Component, OnInit } from '@angular/core';
@Component({
styleUrls: ['./html-viewer.component.css'],
templateUrl: './html-viewer.component.html'
})
export class HtmlViewerComponent implements OnInit {
htmlString = "";
constructor() { }
ngOnInit() {
// 適当なHTML文字列を用意
this.htmlString = "<h2 class='hoge' style='color: red;' onclick='() => alert()'>aaaa</h2>"
}
}
html-viewer.component.html
<div>{{htmlString}}</div>
上記のようなコンポーネントを表示した場合、htmlString
の文字列がそのままブラウザに表示されてしまいます。うまくいかないので別の方法が必要です。
2. innerHTML属性にバインドするとHTMLとして解釈される
実際にHTMLを解釈して表示してほしい場合には、innerHTML 属性を使ってバインドします。
html-viewer.component.html
<div [innerHTML]='htmlString'></div>
innerHTML 属性は、バインドされたデータをHTMLとして解釈して表示します。したがって上記のようになります。しかし、注意しないといけないのが、属性情報が全て欠落するという点です。
idやclass属性は残るようですが、style属性はすべて削除されてしまいます。また、scriptタグは当然エスケープされます。
style属性やscriptも含めて動的に埋め込む場合は別の手段を用いる必要があります。
3. DomSanitizer で セキュリティ処理をパスできる
Angularの内部的なセキュリティ処理をパスさせなければ、HTML文字列を完全に処理させる事はできません。DomSanitizer
を使うことで実現できます。
bypassSecurityTrustHtml()
は、与えられた文字列に対してHTMLで解釈しても大丈夫というマークを与えます。ただし、これは単純にマークするだけなので、実際に表示して安全かどうかは開発者側が担保しなければなりません。
使い方は以下のとおりです。
import { Component, OnInit } from '@angular/core';
import { SafeHtml, DomSanitizer } from '@angular/platform-browser';
@Component({
styleUrls: ['./html-viewer.component.css'],
templateUrl: './html-viewer.component.html'
})
export class HtmlViewerComponent implements OnInit {
safeHtml: SafeHtml;
constructor(private domSanitizer: DomSanitizer) { }
ngOnInit() {
this.safeHtml = this.domSanitizer.bypassSecurityTrustHtml("<h2 class='hoge' style='color: red;' onclick='console.log(1)'>aaaa</h2>");
}
}
html-viewer.component.html
<div [innerHTML]='safeHtml'></div>
style属性もクリックのscriptもうまく動作します。DomSanitizer
のメソッドを使えば、ScriptやStyleタグも動的に埋め込むことが可能です。
最後に上記コードの実行例を並べます。
動的にHTMLを埋め込むのはセキュリティ上の問題を孕む危険があるので利用は最小限にしておきましょう。
以上。
コメントを書く