Angular2 Pipes: output raw HTML

Viewed 64131

I'm trying to create an Angular2 custom pipe that outputs raw html. I want it to simply convert newlines in the input into HTML line breaks. How do I output raw HTML from an angular2 pipe?

The following is my current pipe definition, but it escapes the HTML which I don't want:

import {Pipe, PipeTransform} from '@angular/core';
/*
 * Converts newlines into html breaks
*/
@Pipe({ name: 'newline' })
export class NewlinePipe implements PipeTransform {
    transform(value: string, args: string[]): any {
        return value.replace(/(?:\r\n|\r|\n)/g, '<br />');
    }
}

EDIT: Just a quick note since this question seems to get a number of views and activity that I'm leaving my accepted answer as is, even though for my specific example use-case css probably would have been a better option and was in fact what I changed to. But my actual question was "how do I output raw html from an angular 2 pipe", not "what's the best way to render line breaks" which is what the accepted answer shows.

Beware though, as mentioned in comments below, if you do use the method in the accepted answer you need to ensure that you're not rendering unchecked user input as this could open you up to XSS vulnerabilities.

9 Answers

If you are binding Typescript variable in HTML and it contains '\n' then you need to replace them < br/> otherwise keep < br/> from beginning.

However String interpolation will not break the line you need to use property binding with innerHtml like:

<span [innerHtml]="stringVariableName"></span>
<p *ngFor="let myContent of myContents.split('\n')">{{ myContent }} </p>

This thing will do the same....

Here's my take on it, using a simple pipe

make a file called nl2pbr.pipe (which stands for: new line to p / br) and put it inside pipes folder, and this is its content:

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

@Pipe({
  name: 'nl2pbr'
})
export class Nl2pbrPipe implements PipeTransform {

  transform(value: any, args?: any): any {
    // return value.replace(/\n/g, '<br />');
    value = value.replace(/(?:\r\n\r\n|\r\r|\n\n)/g, '</p><p>');
    return '<p>' + value.replace(/(?:\r\n|\r|\n)/g, '<br>') + '</p>';
  }

/****************************
 * example useage
 * <div [innerHTML]="'testi\n\nng \n t/n/nest\n\b\ning' | translate | nl2pbr"></div>
 ****************************/

}

Make sure you add the pipe to app.module:

import { Nl2pbrPipe } from './pipes/`nl2pbr.pipe`';

and Nl2pbrPipe to the declarations: []

Usage example:

<div [innerHTML]="'hello\n\n this is a new paragraph\n and a new line' | translate | nl2pbr"></div>

will output:

<p>hello</p>
<p>this is a new paragraph <br/> and a new line</p>

use angular directive

import { Directive, ElementRef } from '@angular/core';

@Directive({
    selector: '[shareLineBreaker]',
})
export class LineBreakerDirective {
    constructor(el: ElementRef) {
        el.nativeElement.style['white-space'] = 'pre-line'
    }
}

then

<td shareLineBreaker>
                    {{data.users |  arraymap:'\n':'n':'l' }}
                </td>

What about:

<pre>{{text}}</pre>

Or for html:

<pre [innerHtml]="text"></pre>

I often use the HTML pre element that represents preformatted text.

Another trick I often use to format Json is:

<pre>{{jsonString | json}}</pre>
value.replace(/(?:\\r\\n|\\r|\\n)/g, '<br />');

works for me

Related