Home > Back-end >  Angular - transform innerHtml using two pipes
Angular - transform innerHtml using two pipes

Time:04-21

Used two pipes to make an html markup, from my database, safer and shorter:

@Pipe({ name: 'safe' })
export class SafePipe implements PipeTransform {
  constructor(protected sanitizer: DomSanitizer) {}

     public transform(value: any, type: string): SafeHtml | SafeStyle | SafeScript | SafeUrl | SafeResourceUrl {
        switch (type) {
                case 'html': return this.sanitizer.bypassSecurityTrustHtml(value);
                . . .
            }
      }
    }

and

@Pipe({
  name: 'summary'
})
export class SummaryPipe implements PipeTransform {

  transform(content: string, characterLimit: number): string {
    if (content.length <= characterLimit) {
      return content;
    } else {
      return `${content.substring(0, characterLimit)}...`;
    }
  }

}

Using it with one pipe it works:

<div [innerHtml]="blog.content | safe: 'html'"></div>

But with the second pipe it stops showing:

<div [innerHtml]="blog.content | safe: 'html' | summary:100"></div>

How can I fix it ?

CodePudding user response:

Your summary pipe is expecting a string, but your safe pipe return a SafeValue.

The easiest solution is to use the safe pipe last:

<div [innerHtml]="blog.content | summary:100 | safe: 'html'"></div>

From this issue https://github.com/angular/angular/issues/33028, you have two other solutions:

  1. Using $any() on the result of the safe pipe
<div [innerHtml]="$any(blog.content | safe: 'html') | summary:100"></div>
  1. Change the return type of your safe pipe to string and cast the result to string.
@Pipe({ name: 'safe' })
export class SafePipe implements PipeTransform {
  constructor(protected sanitizer: DomSanitizer) {}
  
  public transform(value: any, type: string): string {
    switch (type) {
      case 'html': return this.sanitizer.bypassSecurityTrustHtml(value) as string;
      . . .
    }
  }
}

CodePudding user response:

  <div [innerHtml]="(blog.content | safe: 'html') | summary:100"></div>

did you try doing this?

  • Related