Patrioticcow Patrioticcow - 2 months ago 163
Javascript Question

innerHtml doesn't work with ionic 2 pipes, how to?

I have a simple pipe that returns some html

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
name: 'rating',
pure: false
})
export class RatingPipe implements PipeTransform {
transform(value: any): string {
let stars = "<ion-icon name='star'>" + value + "</ion-icon>";
return stars;
}
}


the problem is when i use it, i get nothing

// this works fine
<p><span innerHtml="{{'<h1>some text</h1>'}}"></span></p>

// if I add a pipe, it doesn't work
<p><span innerHtml="{{variableFromControler | rating}}"></span></p>

// if I add a pipe, it doesn't work
<p><span [innerHtml]="variableFromControler | rating"></span></p>


any ideas?

One solution

import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizationService } from '@angular/platform-browser'; // to become DomSanitizer

@Pipe({
name: 'rating',
pure: false
})
export class RatingPipe implements PipeTransform {
sanitizer: any;
constructor(private domSanitizationService: DomSanitizationService) {
this.sanitizer = domSanitizationService;
}

transform(value: any): string {
let stars = "<ion-icon class='ion-ios-star'>" + value + "</ion-icon>";

return this.sanitizer.bypassSecurityTrustHtml(stars);
}
}

Answer

It won't work with this html

"<ion-icon name='star'>" + value + "</ion-icon>"

because ion-icon is a ionic-angular component and it should load via angular2 instead of just using innerHTML.

Anyway you should use DomSanitanizeService for your html pipe like this:

@Pipe({
    name: 'rating',
    pure: false
})
export class RatingPipe implements PipeTransform {
    constructor(private domSanitizer: DomSanitizationService){}
    transform(value: any): string {
        let stars = "<div>" + value + "</div>";
        return this.domSanitizer.bypassSecurityTrustHtml(stars);
    }
}

And in your html you have to use property binding:

<span [innerHtml]="text | rating"></span>

I would leverage a custom icon wrapper for your case:

@Component({
  selector: 'ion-rating-icon',
  template: '<ion-icon name="star">{{rating}}</ion-icon>'
}) 
class RatingIconComponent {
  @Input() rating;
} 

Then use it like:

<ion-rating-icon [rating]="text"></ion-rating-icon>

See all examples in Plunker