Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 7: prevent escaping of HTML tags inside a string variable passed to child component through data binding

In my Angular 7 app I have a simple home component using one-way data binding on a string variable (i.e. I pass a variable to a child component using @Input with the [text]="'Some text'" syntax).

I would like to include html tags such as links in the variable and render it in the child component but the code below fails because of the anchor tag. How to fix this?

home.component.ts:

{ Component } from '@angular/core';
@Component({
  selector: 'app-home',
  template: '
    <app-card [text]="'Some text and a link: <a href="https://stackoverflow.com" target="_blank">link</a>'">
    </app-card>
  ',
  styleUrls: ['./home.component.css']
})
export class HomeComponent {}

card.component.ts:

import { Component, Input } from '@angular/core';
@Component({
  selector: 'app-card',
  template: '
    <div class="bla bla">
      <p>{{text}}</p>
    </div>
  ',
  styleUrls: ['./card.component.css']
})
export class CardComponent {
  @Input() text: string;
}

Edit: I wrote 'templateUrl' but that was wrong, I mean 'template'. Let me add that my real card template is more complicated than the div shown here, and I actually use templateUrl in both components as follows:

templateUrl: './about.component.html', //in app component

templateUrl: './card.component.html',  //in card component
like image 751
aless80 Avatar asked Jan 08 '19 08:01

aless80


4 Answers

I actually found how to do it. First, I needed to use innerHTML for the

element:

<p innerHTML={{text}}>{{text}}</p>

Second, some funky syntax. In the parent Home component notice that href and target attributes do not need quotes:

<app-card [text]="'Some text and a link: <a href=https://stackoverflow.com target=_blank>link</a>'">
</app-card>

Edit: Other users point to DOMSanitizer, but that forces me to write the text in the typescript part of the app component, not in the template part. As @John Velasquez says in another answer, this "solution is more likely a constant that cannot be changed anymore its more likely a one-way binding."

like image 113
aless80 Avatar answered Oct 22 '22 18:10

aless80


This is by far the best and cleanest way to do it

Angular 2: Display HTML without sanitizing/filtering

1) Create new file to hold the pipe pipes/keep-html.pipe.ts:

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

    @Pipe({ name: 'keepHtml', pure: false })

export class EscapeHtmlPipe implements PipeTransform {
  constructor(private sanitizer: DomSanitizer) {
  }

  transform(content) {
    return this.sanitizer.bypassSecurityTrustHtml(content);
  }
}

2) Add an import statement in your app.module.ts:

import { EscapeHtmlPipe } from './pipes/keep-html.pipe';
@NgModule({
  declarations: [
    EscapeHtmlPipe
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}

3) Finally use that pipe in your template:

<div [innerHTML]="post.body | keepHtml"></div>

đź‘Ź Kudos to Ammar Alakka for sharing this solution đź‘Ź.

like image 34
Eduardo A. Fernández Díaz Avatar answered Oct 22 '22 18:10

Eduardo A. Fernández Díaz


use DomSanitizer to bypass html

import { Component, Input } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
@Component({
  selector: 'app-card',
  templateUrl: '
    <p [innerHtml]="result"></p>
  ',
  styleUrls: ['./card.component.css']
})
export class CardComponent implements OnInit {
  @Input() text: string;

  result: any;
  constructor(private sanitized: DomSanitizer) {

  }

  ngOnInit() {
    this.result = this.sanitized.bypassSecurityTrustHtml(this.text);
  }
}

see stackblitz for complete guide https://stackblitz.com/edit/angular-w6qys9

like image 5
John Velasquez Avatar answered Oct 22 '22 17:10

John Velasquez


for links you can use

<a [href]="text">Angular Docs</a>

If you want to pass a big html block, you'll need [innerHtml] https://angular.io/guide/template-syntax#property-binding-or-interpolation

See : https://angular.io/guide/ajs-quick-reference

like image 1
andrea06590 Avatar answered Oct 22 '22 18:10

andrea06590