Применение стилей к внутреннему HTML в Angular

У меня есть компонент Angular с именем ExternalHtmlComponent, отвечающий за рендеринг HTML-контента, полученного из серверной части. Содержимое HTML динамически вставляется в элемент с помощью привязки свойства [innerHTML]. Чтобы стилизовать динамически вставляемый HTML-контент, я определил миксин external-html в файлеComponents/external-html.scss. Однако эти стили не применяются к тегам.

Как я могу гарантировать, что все стили, определенные в external-html.scss, правильно применяются к соответствующим элементам HTML в динамически вставленном HTML?

components/external/external_html.component.ts

import {Component, ViewEncapsulation, Input, OnInit} from '@angular/core';

@Component({
  selector: 'component-external-html',
  template: '<div [innerHTML] = "html"> </div>',
  styleUrls: ['./external-html.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class ExternalHtmlComponent {

  @Input() html: string;

  constructor() { }

}

components/external/external_html.component.scss

@import "components/external-html";

:host {
  @include external-html;
}

components/external-html.scss

@mixin external-html {
    font: var(--font-body);
    color: var(--color-text); // only these changes are applied, when inspected.
    // if I add background color here, <a> tags gets it.

    h1 {
        font: var(--font-subtitle);
    }
    
    h2 {
        font: var(--font-label-bold);
        text-transform: uppercase;
        color: var(--color-secondary);
    }
    
    h3 {
        font: var(--font-emphasis);
    }
    
    b, strong {
        font: var(--font-body-semibold);
        background-color: red;
    }
    
    a {
        font: var(--font-body-semibold);
        color: var(--color-primary);
        text-decoration: underline;
    }
    
    blockquote {
        display: inline-flex;
        justify-content: center;
        align-items: center;
        padding: var(--spacing-2);
        border-radius: var(--border-radius-2);
        background-color: var(--color-primary-05);
    }
}

Вот его использование:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-external-html-example',
  template: '<component-external-html [innerHTML] = "exampleHtmlContent"></component-external-html>',
})
export class ExternalHtmlExampleComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

  public exampleHtmlContent: string = `
  <h1>This is a Heading 1</h1>
  <h2>This is a Heading 2</h2>
  <h3>This is a Heading 3</h3>
  <p>This is a paragraph with <b>bold</b> text.</p>
  <a href = "#">This is a link</a>
  <ul>
    <li>Unordered list item 1</li>
    <li>Unordered list item 2</li>
  </ul>
  <ol>
    <li>Ordered list item 1</li>
    <li>Ordered list item 2</li>
  </ol>
  <blockquote>
    This is a blockquote with background color, padding, and rounded corners.
  </blockquote>
`;

}

🤔 А знаете ли вы, что...
С JavaScript можно создавать расширения для различных платформ, таких как Adobe Acrobat и Microsoft Office.


2
77
3

Ответы:

Решено

Я вижу проблему, вам нужно передать [html] вместо [innerHTML] в строке ниже!

...
@Component({
  selector: 'app-external-html-example',
  template: '<component-external-html [html] = "exampleHtmlContent"></component-external-html>',
})
...

[innerHTML] по большей части уничтожил компонент, поэтому стили не были применены - это моя теория!


Содержимое, отображаемое внутри innerHTML, технически не является частью компонента, поэтому нам нужно поместить CSS внутрь global-styles.scss, тогда он будет применен к элементам InnerHTML, в ViewEncapsulation.None нет необходимости!

/* Add application styles & imports to this file! */

@import './app/test/components/external-html';

component-external-html {
  @include external-html;
}

Демо-версия Stackblitz


Селектор :host нацелен только на хост-элемент компонента.

Итак, вам нужно обернуть стиль селектором CSS компонента вместо хоста.

Пытаться:

@Component({
  selector: 'component-external-html', ------> component'css selector
  template: '<div [innerHTML] = "html"> </div>',
  styleUrls: ['./external-html.component.scss'],
  encapsulation: ViewEncapsulation.None
})

// стили.

   @import "components/external-html";

    component-external-html {
      @include external-html;
    }

Я решил проблему, добавив ::ng-deep в SCSS файл компонента.

:host ::ng-deep {
    @include external-html;
}

Также я увидел, что в некоторых случаях необходимо определить encapsulation: ViewEncapsulation.None Но в моем случае это не имело значения.