skip to Main Content

I have an Angular component named ExternalHtmlComponent responsible for rendering HTML content fetched from the backend. The HTML content is dynamically inserted into a element using the [innerHTML] property binding. To style the dynamically inserted HTML content, I’ve defined a mixin called external-html in the components/external-html.scss file. However these styles are not applied to tags.

How can I ensure that all styles defined in external-html.scss are correctly applied to the corresponding HTML elements within the dynamically inserted 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);
    }
}

Here is the usage of it:

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>
`;

}

3

Answers


  1. Chosen as BEST ANSWER

    I resolved the issue by adding ::ng-deep in SCSS file of component.

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

    Also I saw that in some cases, you have to define the encapsulation: ViewEncapsulation.None But in my case it didn't matter.


  2. I can see a problem, you need to pass [html] instead of [innerHTML] in the below line!

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

    [innerHTML] mostly destroyed the component so the styles did not get applied is my theory!


    The content rendered inside the innerHTML is not technically part of the component so we need to put the CSS inside global-styles.scss then it will get applied to the innerHTML elements, there is no need for ViewEncapsulation.None!

    /* Add application styles & imports to this file! */
    
    @import './app/test/components/external-html';
    
    component-external-html {
      @include external-html;
    }
    

    Stackblitz Demo

    Login or Signup to reply.
  3. The :host selector only targets the host element of a component.

    So, you need to wrap the style with the component’s css selector instead of host.

    Try:

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

    // styles.

       @import "components/external-html";
    
        component-external-html {
          @include external-html;
        }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search