Angular 2 - innerHTML-стиль
Я получаю фрагменты HTML-кодов из HTTP-вызовов. Я помещаю блоки HTML в переменную и вставляю ее на свою страницу с помощью [innerHTML], но не могу стилизовать вставленный блок HTML. У кого-нибудь есть предложения, как мне этого добиться?
@Component({selector: 'calendar',
template: '<div [innerHTML]="calendar"></div>',
providers:[HomeService],
styles: [`
h3 {color:red;}
`})
HTML-код, который я хочу оформить, представляет собой блок, содержащийся в переменной "calendar".
13 ответов
обновление 2::slotted
::slotted
теперь поддерживается всеми новыми браузерами и может использоваться с `ViewEncapsulation.ShadowDom
https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted
обновление 1::ng-deep
/deep/
устарела и заменена ::ng-deep
,
::ng-deep
также уже помечен как устаревший, но пока нет замены.
когда ViewEncapsulation.Native
правильно поддерживается всеми браузерами и поддерживает стилизацию через теневые границы DOM, ::ng-deep
вероятно будет прекращено.
оригинал
Angular добавляет все виды CSS-классов в HTML-код, добавляемый в DOM для эмуляции теневой DOM-инкапсуляции CSS, чтобы предотвратить появление стилей в компонентах. Angular также переписывает CSS, который вы добавляете, для соответствия этим добавленным классам. Для HTML добавлено с помощью [innerHTML]
эти классы не добавляются, и переписанный CSS не совпадает.
В качестве обходного пути попробуйте
- для CSS добавлен в компонент
/* :host /deep/ mySelector { */
:host ::ng-deep mySelector {
background-color: blue;
}
- для CSS добавлен в
index.html
/* body /deep/ mySelector { */
body ::ng-deep mySelector {
background-color: green;
}
>>>
(и эквивалент/deep/
но /deep/
лучше работает с SASS) и ::shadow
были добавлены в 2.0.0-бета.10. Они похожи на CSS-комбинаторы теневого DOM (которые устарели) и работают только с encapsulation: ViewEncapsulation.Emulated
который используется по умолчанию в Angular2. Они, вероятно, также работают с ViewEncapsulation.None
но тогда игнорируются только потому, что они не нужны. Эти комбинаторы являются лишь промежуточным решением, пока не поддерживаются более продвинутые функции для многокомпонентного стиля.
Другой подход заключается в использовании
@Component({
...
encapsulation: ViewEncapsulation.None,
})
для всех компонентов, которые блокируют ваш CSS (зависит от того, где вы добавляете CSS и где находится HTML, который вы хотите стилизовать - это могут быть все компоненты в вашем приложении)
Обновить
Вам нужно следовать простому решению:
import { DomSanitizer } from '@angular/platform-browser';
constructor(private sanitizer: DomSanitizer){}
transformYourHtml(htmlTextWithStyle) {
return this.sanitizer.bypassSecurityTrustHtml(htmlTextWithStyle);
}
Мы часто загружаем контент из нашей CMS как [innerHTML]="content.title"
. Помещаем необходимые классы в корень приложенияstyles.scss
файл, а не в scss-файле компонента. Наша CMS намеренно удаляет встроенные стили, поэтому мы должны подготовить классы, которые автор может использовать в своем контенте. Помните использование{{content.title}}
в шаблоне не будет отображать html из содержимого.
Если вы пытаетесь стилизовать динамически добавленные элементы HTML внутри компонента Angular, это может быть полезно:
// inside component class...
constructor(private hostRef: ElementRef) { }
getContentAttr(): string {
const attrs = this.hostRef.nativeElement.attributes
for (let i = 0, l = attrs.length; i < l; i++) {
if (attrs[i].name.startsWith('_nghost-c')) {
return `_ngcontent-c${attrs[i].name.substring(9)}`
}
}
}
ngAfterViewInit() {
// dynamically add HTML element
dynamicallyAddedHtmlElement.setAttribute(this.getContentAttr(), '')
}
Я предполагаю, что соглашение для этого атрибута не гарантируется стабильным между версиями Angular, поэтому при обновлении до новой версии Angular могут возникнуть проблемы с этим решением (хотя обновление этого решения, вероятно, будет тривиальным в этом дело).
Используйте метод ниже, чтобы разрешить стили CSS в
innerhtml
.
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
.
.
.
.
html: SafeHtml;
constructor(protected _sanitizer: DomSanitizer) {
this.html = this._sanitizer.bypassSecurityTrustHtml(`
<html>
<head></head>
<body>
<div style="display:flex; color: blue;">
<div>
<h1>Hello World..!!!!!</h1>
</div>
</div>
</body>
</html>`);
}
Пример кода stackblitz
Или используйте метод ниже, чтобы писать прямо в HTML.https://gist.github.com/klihelp/4dcac910124409fa7bd20f230818c8d1
Самый простой и понятный - использовать файл глобальных стилей, расположенный в папке src проекта angular.
Предполагая, что селектор компонентов: app-my-component
Добавьте класс к элементу, содержащему содержимое innerHtml в шаблоне app-my-component:
<div class="innerhtml-class" [innerHTML]="variable.innerHtml"></div>
Добавьте в файл глобальных стилей:
app-my-component {
.innerhtml-class {
declaration goes here
}
}
Рекомендуемая версия Günter Zöchbauer работает нормально, но мне нужно сделать дополнение. В моем случае у меня был нестилизованный html-элемент, и я не знал, как его стилизовать. Поэтому я разработал трубу, чтобы добавить ей стиля.
import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
@Pipe({
name: 'StyleClass'
})
export class StyleClassPipe implements PipeTransform {
constructor(private sanitizer: DomSanitizer) { }
transform(html: any, styleSelector: any, styleValue: any): SafeHtml {
const style = ` style = "${styleSelector}: ${styleValue};"`;
const indexPosition = html.indexOf('>');
const newHtml = [html.slice(0, indexPosition), style, html.slice(indexPosition)].join('');
return this.sanitizer.bypassSecurityTrustHtml(newHtml);
}
}
Затем вы можете добавить стиль к любому html-элементу следующим образом:
<span [innerhtml]="Variable | StyleClass: 'margin': '0'"> </span>
С участием:
Variable = '<p> Test </p>
Альтернативой использованию классов CSS внутри [innerHTML] является объявление их в глобальном файле, например,styles.scss. Этот файл указан в angular.json.
"styles": [
"./node_modules/flexboxgrid/dist/flexboxgrid.min.css",
"src/styles.scss"
],
Для всех, кто хочет, просто применяет определенный стиль к innerHTML:
Следуйте инструкциям по созданию безопасного канала HTML
И вы можете объединить свою HTML-строку со стилем CSS следующим образом:
return this.sanitizer.bypassSecurityTrustHtml(value+='<style type="text/css">.image img { width: 100% }</style>');
Этот
value
из преобразования (значение, ... аргументы)
Я пошел
this.sanitizer.bypassSecurityTrustHtml()
route изначально и установил инкапсуляцию на, но возникли 2 проблемы:
-
ViewEncapsulation.NONE
вызывал другие проблемы со стилем в моем компоненте - Мой "безопасный" html не работал с переменными css, т.е. var(- синий)
Это сработало для меня (без необходимости ничего менять): InsertAdjacentHTML
Шаблон:
<div id=template></div>
Код:
ngOnInit() {
const d1 = document.getElementById('template');
d1.insertAdjacentHTML('afterbegin', `<span style="color: var(--blue)">hello</span>`);
}
Отказ от ответственности : в моем случае я разбирал html из файлов конфигурации. Вы бы не хотели идти по этому пути с введенным пользователем html.
Использование встроенных переменных CSS является альтернативным решением, если у вас ограниченное количество динамических стилей.
Т.е.
// file.ts
someVarWithHtml = 'Hello <span class="dynamic">World</span>';
// file.ng.html
<div [style]="'--my-var: ' + value"
[innerHTML]="someVarWithHtml"></div>
// style.css
.dynamic {
background: var(--my-var);
}
Используйте метод ниже, чтобы разрешить стили css в
innerhtml
.
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
.
.
.
.
html: SafeHtml;
constructor(protected _sanitizer: DomSanitizer) {
this.html = this._sanitizer.bypassSecurityTrustHtml(`
<html>
<head></head>
<body>
<div style="display:flex; color: blue;">
<div>
<h1>Hello World..!!!!!</h1>
</div>
</div>
</body>
</html>`);
}
Пример кода stackblitz
Или используйте метод ниже, чтобы писать прямо в html. https://gist.github.com/klihelp/4dcac910124409fa7bd20f230818c8d1
Если вы используете sass в качестве препроцессора стиля, вы можете вернуться к собственному компилятору Sass для зависимости от разработчиков:
npm install node-sass --save-dev
Чтобы вы могли продолжать использовать /deep/ для разработки.