Angular 2 - innerHTML-стиль

170

Я получаю фрагменты HTML-кодов из HTTP-вызовов. Я помещаю блоки HTML в переменную и вставляю ее на мою страницу с помощью [innerHTML], но не могу стилизовать вставленный блок HTML. У кого-нибудь есть предложения, как мне этого добиться?

@Component({selector: 'calendar',
template: '<div [innerHTML]="calendar"></div>',
providers:[HomeService], 
styles: [` 
h3 {color:red;}
`})

HTML-код, который я хочу оформить, представляет собой блок, содержащийся в переменной «calendar».

Якоб Свеннингссон
источник
Стиль откуда? Из компонента или из стилей, добавленных в index.html?
Гюнтер Цохбауэр
что вы имеете в виду can not style the inserted HTML block? Покажите нам, что сделали для этого с небольшим фрагментом кода.
micronyks
Я обновил свой пост фрагментом кода! :) спасибо
Якоб Свеннингссон
1
Я добавил ссылку Plunker в свой ответ
Гюнтер Цохбауэр
@ GünterZöchbauer, что если HTML-коды имеют встроенные CSS? как это будет оказано?
Иниравпател

Ответы:

320

обновление 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, который вы хотите стилизовать - это могут быть все компоненты в вашем приложении)

Обновить

Пример Плункер

Гюнтер Цохбауэр
источник
6
Просто примечание для всех, это не работает ни с node-sass, ни с styleUrl. Только в стилях: [...]
thouliha
12
С использованием SASS /deep/вместо>>>
Günter Zöchbauer
1
Вы можете добавить директивы или компоненты в содержаниеinneeHTML
Günter Zöchbauer
1
Если HTML-код, предоставляемый HTTP-вызовом, большой и имеет встроенный CSS, как это будет возможно, поскольку у меня нет предопределенных стилей, я получаю его только из встроенного CSS @ GünterZöchbauer
iniravpatel
1
Спас день в Angular 8! Thanx. Трудно понять вопрос правильно, чтобы найти этот ответ!
пианист
12

Простое решение, которому вы должны следовать,

import { DomSanitizer } from '@angular/platform-browser';

constructor(private sanitizer: DomSanitizer){}

transformYourHtml(htmlTextWithStyle) {
    return this.sanitizer.bypassSecurityTrustHtml(htmlTextWithStyle);
}
Сахиль Ралкар
источник
2

Если вы пытаетесь стилизовать динамически добавленные элементы 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 могут возникнуть проблемы с этим решением (хотя обновление этого решения, вероятно, будет тривиальным в этом кейс).

Тревор
источник
2

Мы часто загружаем контент из нашей CMS as [innerHTML]="content.title". Мы styles.scssпомещаем необходимые классы в корневой файл приложения, а не в файл scss компонента. Наша CMS намеренно удаляет встроенные стили, поэтому мы должны подготовить классы, которые автор может использовать в своем контенте. Помните, что использование {{content.title}}в шаблоне не будет отображать HTML из содержимого.

Lyfo
источник
-3

Если вы используете sass в качестве препроцессора стиля, вы можете переключиться обратно на собственный компилятор Sass для зависимости dev:

npm install node-sass --save-dev

Так что вы можете продолжать использовать / deep / для разработки.

Брайан Лу
источник