Search code examples
htmlcssangulartypescriptinnerhtml

ViewEncapsulation.None not working with innertHTML



I'm actually developing an angular application and I have to put an [innerHTML] element in a div.

My code
Like that :
something.component.html

<section class="mx-auto" *ngFor="let publication of publication">
  <div [innerHTML]="publication.content"></div>
</section>

So in ts :
something.component.ts

import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { Subscription } from 'rxjs';
import { ActivatedRoute } from '@angular/router';
import { Title, Meta } from '@angular/platform-browser';

import { Publication } from '../publication.model';
import { PublicationsService } from '../publication.service';

@Component({
  selector: 'app-free-publication',
  templateUrl: './something.component.html',
  styleUrls: ['./something.component.scss'],
  encapsulation: ViewEncapsulation.None
})

export class FreePublicationComponent implements OnInit {
  publication: Publication[] = [];
  suggestions: Publication[] = [];
  private routeSub: Subscription;
  getId: any;
  isLoading = false;

  constructor(public publicationsService: PublicationsService, private route: ActivatedRoute, private titleService: Title, private meta: Meta) {
    this.getId = this.route.url['_value'][1].path;
    this.getId = + this.getId;
  }

  ngOnInit() {
    this.isLoading = true;
    // main publication
    this.routeSub = this.route.params.subscribe(params => {
      this.publicationsService.getPublication(params['publicationId']).then(dataPublication => {
        for (let i = 0; (dataPublication.content.match(/wp-content/g) || []).length; i++) {
          dataPublication.content = dataPublication.content.replace('https://aurelienbamde.com/wp-content/', 'assets/content/');
        }
        this.titleService.setTitle(dataPublication.title);
        this.meta.addTag({ name: 'keywords', content: dataPublication.post_tag });
        this.publication = [dataPublication];
      });
    });
  }
}

And my innertHTML do not return the style of the html doc that I send.

My tests
With a console.log() at the end of ngOnInit, I can see my html with all of the styles attributs, but by inspecting the div of the innerHTML, there is no style inside.

My question
So I well implement ViewEncapsulation.None as you see, there is an action on other elements, so it works, but not on my innerHTML.
Do you have any idea, problem of version ? Or coworking with others elements ?

Thanks in advance for your time !
And I wish you success in your projects.


Solution

  • You must bypass the security imposed by angular for dangerous content (HTML content not generated by the app). There is a service, called DomSanitizer that enables you to declare a content as safe, preventing angular to filter potentially harm things to be used like styles, classes, tags etc. You basically need to pass your content through this sanitizer using a pipe:

    <div [innerHTML]="dangerousContent | safeHtml"></div>
    

    Your SafeHtmlPipe would be something like this:

    @Pipe({name: 'safeHtml'})
    export class SafeHtmlPipe implements PipeTransform {
    
      constructor(protected sanitizer: DomSanitizer) {}
    
      transform(value: string): SafeHtml {
        return this.sanitizer.bypassSecurityTrustHtml(value)
      }
    }
    

    There are other bypassSecurityTrust* methods in DomSanitizer:

    • bypassSecurityTrustScript

    • bypassSecurityTrustStyle

    • bypassSecurityTrustUrl

    • bypassSecurityTrustResourceUrl

    You can find more info in Angular docs.