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
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."
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 đź‘Ź.
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With