Angular и работа с опасным контентом (html, js, css)

Запись от 10.06.2017

По умолчанию, все пришедшие данные (ajax, пользовательский ввод, например) Angular считает небезопасными и выводит на странице соответственным образом, то есть просто текстом. А попытка использовать style или js вообще вызовет в консоли warnings.

В этом посте я хочу выделить 3 типа данных: html, js, css. Angular приложение доверяет только тем стилям, разметки и скриптам, что были включены в него на этапе сборки, поэтому для использования их постфактум можно использовать следующие приемы.


HTML

Самый простой способ вывести html данные в шаблоне — использовать свойство innerHtml вот так:

<div [innerHtml]="post.DETAIL_TEXT"></div>


Но лучше дополнить использование фильтра (pipe), который прогонит данные через встроенный в ядро ангуляра sanitizer. Сам pipe выглядит так:

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

@Pipe({name: 'safeHtml'})
export class SafeHtmlPipe implements PipeTransform {
	constructor(
		private sanitized: DomSanitizer,
	) {}

	transform(value) {
		return this.sanitized.bypassSecurityTrustHtml(value);
	}
}


После объявления SafeHtmlPipe в модуле им можно пользоваться в шаблоне:

<div [innerHtml]="post.DETAIL_TEXT | safeHtml"></div>

JavaScript

Для вставки и выполнения внешнего javascript-кода понадобится больше действий:

export class MyComponent implements OnInit {
	constructor(
		private render: Renderer2,
		private el: ElementRef,
	) {}

	setScript(scriptSrc) {
		const script = this.render.createElement('script');
		script.type = 'text/javascript';
		script.src = scriptSrc;
		this.render.appendChild(this.el.nativeElement, script);
	}
} 
Таким образом, с помощью Renderer2 и ElementRef компонент имеет возможность добавлять в свой шаблон необходимые скрипты.


CSS

Использование CSS аналогично js:

const script = this.render.createElement('link');
script.rel = 'stylesheet';
script.type = 'text/css';
script.href = src;
this.render.appendChild(this.el.nativeElement, script);


Эти приемы пригодились мне в настройке страницы про tilt-эффект для фотографий.