I am writing an Angular application, and I have an HTML response I want to display. How do I do that? If I simply use the binding syntax {{myVal}} it encodes all HTML characters (of course).

I need somehow to bind the inner html of a div to the variable value.

upvote
  flag
Related post for getting CSS defined in a component to work right in the HTML binding //allinonescript.com/questions/36265026/… – y3sh

15 Answers 11

I apologize if I am missing the point here, but I would like to recommend a different approach:

I think it's better to return raw data from your server side application and bind it to a template on the client side. This makes for more nimble requests since you're only returning json from your server.

To me it doesn't seem like it makes sense to use Angular if all you're doing is fetching html from the server and injecting it "as is" into the DOM.

I know Angular 1.x has an html binding, but I have not seen a counterpart in Angular 2.0 yet. They might add it later though. Anyway, I would still consider a data api for your Angular 2.0 app.

I have a few samples here with some simple data binding if you are interested: http://www.syntaxsuccess.com/viewarticle/angular-2.0-examples

upvote
  flag
After spending a few hours last night on this, I reached the same conclusion. – Aviad P.
19 upvote
  flag
There's definitely use cases where you'd want to fetch and display raw html. E.g. fetching a formatted piece of article from remote. – Alexander Chen
2 upvote
  flag
Another often-ignored scenario is protecting the business logic in the template, you sometimes don't want unauthorized users to see the logic you are using to display information, so you would rather prepare the view on server side – Ayyash
2 upvote
  flag
Also, displaying an HTML email, for example - fair point/question though! – a darren
upvote
  flag
If you are missing the point (which you seem to be by your own admission), then why post a response? Obviously the point of Angular is to use its view engine to bind and render the data. But considering the fact that there are countless applications where an Angular app might be used, it is actually feasible that one or two of them might have the requirement that some of the data that needs to be displayed in your application may already be formatted HTML, and it might just happen to be the case where the developer does not have control over that content. In other words... relevant question. – Gregor
upvote
  flag
This feels like a SPAM answer. – Serj Sagan

This works for me: <div innerHTML = "{{ myVal }}"></div> (Angular2, Alpha 33)

According to another SO: Inserting HTML from server into DOM with angular2 (general DOM manipulation in Angular2), "inner-html" is equivalent to "ng-bind-html" in Angular 1.X

1 upvote
  flag
This didn't work for me – Shervin Asgari
upvote
  flag
thanks...worked for me! – Elon Zito
upvote
  flag
The correct way is without the {{ }}: <div innerHTML = "myVal"></div> – Christian Benseler
upvote
  flag
Use the [property] binding syntax instead of the {{interpolation}} – superluminary

On angular2@2.0.0-alpha.44:

Html-Binding will not work when using an {{interpolation}}, use an "Expression" instead:

invalid

<p [innerHTML]="{{item.anleser}}"></p>

-> throws an error (Interpolation instead of expected Expression)

correct

<p [innerHTML]="item.anleser"></p>

-> this is the correct way.

you may add additional elements to the expression, like:

<p [innerHTML]="'<b>'+item.anleser+'</b>'">></p>

hint

HTML added using [innerHTML] (or added dynamically by other means like element.appenChild() or similar) won't be processed by Angular in any way except sanitization for security purposed.
Such things work only when the HTML is added statically to a components template. If you need this, you can create a component at runtime like explained in How can I use/create dynamic template to compile dynamic Component with Angular 2.0?

1 upvote
  flag
Edited after trying out again. Solution found :) – jvoigt
1 upvote
  flag
The third example not working. The expression is not evaluate. The output is simply string... Any other way to combile trustedHTML with another tags elements ? – Kévin Vilela Pinto
up vote 630 down vote accepted

The correct syntax is now the following:

<div [innerHTML]="theHtmlString"></div>

Working in 5.0.2

Documentation Reference

1 upvote
  flag
7 upvote
  flag
Is there any way I can force angular to run its binding on the elements of that innerHTML? I need to use an <a [router-link]="..."></a>, and want to provide that from external html. – thouliha
2 upvote
  flag
@thouliha I would recommend starting a new post regarding your question. – prolink007
2 upvote
  flag
It renders the string in my case, but does something to the markup. Seems to have stripped out attributes on markup . I'm on 2.4.6 – paqogomez
upvote
  flag
Very helpful. Thanks :) – Kushal Jayswal
upvote
  flag
@paqogomez Yes, it strips out anything it deems unsafe – Juan Mendes

Just to make for a complete answer, if your html content is in a component variable, you could also use:

<div [innerHTML]=componementVariableThatHasTheHtml></div>

[innerHtml] is great option in most cases, but it fails with really large strings or when you need hard-coded styling in html.

I would like to share other approach:

All you need to do, is to create a div in your html file and give it some id:

<div #dataContainer></div>

Then, in your Angular 2 component, create reference to this object (TypeScript here):

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

@Component({
    templateUrl: "some html file"
})
export class MainPageComponent {

    @ViewChild('dataContainer') dataContainer: ElementRef;

    loadData(data) {
        this.dataContainer.nativeElement.innerHTML = data;
    }
}

Then simply use loadData function to append some text to html element.

It's just a way that you would do it using native javascript, but in Angular environment. I don't recommend it, because makes code more messy, but sometimes there is no other option.

See also Angular 2 - innerHTML styling

1 upvote
  flag
I don't see a difference to the other solutions except that yours accesses properties of nativeElement directly which is considered bad practice. I'm sure [innerHTML]="..." does the same under the hood but in good Angular2 practice way. – Günter Zöchbauer
upvote
  flag
Other solutions save string to html attribute first, than loads html. Saving large string to attribute causes browser freezes or even crashes. My solution omits this "attribute part" – Piotrek
1 upvote
  flag
That's not how Angular2 works. The HTML you add to templates of Angular2 components is first processed by Angular and only afterwards added to the DOM. Did you actually experience issues with [innerHTML] and large strings in Angular2? – Günter Zöchbauer
upvote
  flag
Yep, otherwise I wouldn't add my answer here – Piotrek
upvote
  flag
I think this should be reported as bug. Thanks for posting your result. – Günter Zöchbauer
15 upvote
  flag
[innerHtml] removes styling hard-coded in the Html. In order to integrate a wysiwyg editor, I had to use the approach listed here. – Jony Adamit
1 upvote
  flag
This is useful for generating content that will go into an HTML email where inline styling is unfortunately still necessary. Other methods using interpolation removed the inline styles. – Frank
1 upvote
  flag
For me this solution worked for including an inline SVG document, while the [innerHTML] approach didn't. – Jared Phelps
upvote
  flag
An even more "correct" and decoupled way would be to access the element via the renderer and not directly on the nativeElement. Like described here: //allinonescript.com/a/38003377/2477307 – BobbyTables
upvote
  flag
in my case i had also use this approach because i want to set also styles and [innerHtml] cut them off. – Adrian Deja
upvote
  flag
When using the github.com/platosha/angular-polymer lib, then this is the only way at the moment to display dynamic HTML. – Marc Borni
1 upvote
  flag
Can this @ViewChild work for multiple div s? and if so, how? – Guram
upvote
  flag
Thanks for solution, partially worked. My html content has JS/Css links which is not rendering. Due to which I am getting my page broken, partially loaded. How can I fix that? Struggling last 1 day. @Piotrek – Pawan Mittal
upvote
  flag
Hi @PawanMittal, I personally haven't faced that kind of problem, but here is what I found after quick google search //allinonescript.com/a/39959424/1804027 . Seems that browser doesn't render it because of some safety reasons. – Piotrek
upvote
  flag
How do you set div ID #some.id if some.id is a variable and not a static name? – blueprintChris

Working in AngularJS v2.1.1

<div [innerHTML]="variable or htmlString">
</div>
2 upvote
  flag
This produces: <div _ngcontent-luf-0=""></div> for me. The div is empty. – Scott Marcus

Angular 2.0.0 and Angular 4.0.0 final

For safe content just

<div [innerHTML]="myVal"></div>

DOMSanitizer

Potential unsafe HTML needs to be explicitly marked as trusted using Angulars DOM sanitizer so doesn't strip potentially unsafe parts of the content

<div [innerHTML]="myVal | safeHtml"></div>

with a pipe like

@Pipe({name: 'safeHtml'})
export class Safe {
  constructor(private sanitizer:DomSanitizer){}

  transform(style) {
    return this.sanitizer.bypassSecurityTrustHtml(style);
    //return this.sanitizer.bypassSecurityTrustStyle(style);
    // return this.sanitizer.bypassSecurityTrustXxx(style); - see docs
  }
}

See also In RC.1 some styles can't be added using binding syntax

And docs: https://angular.io/api/platform-browser/DomSanitizer

Security warning

Trusting user added HTML may pose a security risk. The before mentioned docs state:

Calling any of the bypassSecurityTrust... APIs disables Angular's built-in sanitization for the value passed in. Carefully check and audit all values and code paths going into this call. Make sure any user data is appropriately escaped for this security context. For more detail, see the Security Guide.

Angular markup

To add HTML that contains Angular-specific markup (property or value binding, components, directives, pipes, ...) it is required to add the dynamic module and compile components at runtime. This answer provides more details How can I use/create dynamic template to compile dynamic Component with Angular 2.0?

upvote
  flag
Useful for rendering HTML email bodies, as they tend to have styles embedded. – a darren
6 upvote
  flag
This should be the answer. Pay attention to the two lines that are commented out. It is actually the second one that handles HTML. – paqogomez
4 upvote
  flag
be sure to import { BrowserModule, DomSanitizer } from '@angular/platform-browser' – paqogomez
3 upvote
  flag
Also import { Pipe } from '@angular/core' – Appulus
1 upvote
  flag
This is the answer, right here! Was looking for the details about what in NG2 replaced $SCE of NG1. ;) – jrista
2 upvote
  flag
Great answer. Solved my issue. Thanks a lot. In case someone's not sure how to use the pipe in a component (like I was): angular.io/guide/pipes Just add it to your declarations in the corresponding module and voilá! – Alejandro Nagy
upvote
  flag
[ts] Property 'bypassSecurityTrustHtml' does not exist on type 'Sanitizer'.? – Rolando
upvote
  flag
Use DomSanitizer instead – Günter Zöchbauer
1 upvote
  flag
Best answer! Thanks – yonexbat

Using [innerHTML] directly without using Angular's DOM sanitizer is not an option if it contains user-created content. The safeHtml pipe suggested by @GünterZöchbauer in his answer is one way of sanitizing the content. The following directive is another one:

import { Directive, ElementRef, Input, OnChanges, Sanitizer, SecurityContext,
  SimpleChanges } from '@angular/core';

// Sets the element's innerHTML to a sanitized version of [safeHtml]
@Directive({ selector: '[safeHtml]' })
export class HtmlDirective implements OnChanges {
  @Input() safeHtml: string;

  constructor(private elementRef: ElementRef, private sanitizer: Sanitizer) {}

  ngOnChanges(changes: SimpleChanges): any {
    if ('safeHtml' in changes) {
      this.elementRef.nativeElement.innerHTML =
        this.sanitizer.sanitize(SecurityContext.HTML, this.safeHtml);
    }
  }
}

To be used

<div [safeHtml]="myVal"></div>
upvote
  flag
I tried to use this but am getting the following error Can't bind to 'safeHtml' since it isn't a known property of 'div'. ng-version 2.4.4 – Obasi Obeny Oj
upvote
  flag
@ObasiObenyOj you can still do that without the using of a separate directive if is a limited case, constructor( private sanitizer: Sanitizer) {} and bind the result into whatever you need, also the usage of ElementRef is strongly unsuggested. – Vale Steve

In Angular 2 you can do 3 types of bindings:

  • [property]="expression" -> Any html property can link to an
    expression. In this case, if expression changes property will update, but this doesn't work the other way.
  • (event)="expression" -> When event activates execute expression.
  • [(ngModel)]="property" -> Binds the property from js (or ts) to html. Any update on this property will be noticeable everywhere.

An expression can be a value, an attribute or a method. For example: '4', 'controller.var', 'getValue()'

Example here

try this code

your string with html tag like below

htmlString:string = "Hello<br/>Html"

you can get the string in html page

<ion-content>
<ion-item>
<div [innerHTML] = "'<p>' + htmlString + '</p>'"></div>
</ion-item>
</ion-content>

Just simply use [innerHTML] attribute in your HTML, something like this below:

<div [innerHTML]="myVal"></div>

Ever had properties in your component that contain some html markup or entities that you need to display in your template? The traditional interpolation won't work, but the innerHTML property binding comes to the rescue.

Using {{myVal}} Does NOT work as expected! This won't pick up the HTML tags like <p>, <strong> etc and pass it only as strings...

Imagine you have this code in your component:

const myVal:string ='<strong>Stackoverflow</strong> is <em>helpful!</em>'

If you use {{myVal}}, you will get this in the view:

<strong>Stackoverflow</strong> is <em>helpful!</em>

but using [innerHTML]="myVal"makes the result as expected like this:

Stackoverflow is helpful!

The way to dynamically add elements to DOM, as explained on Angular 2 doc, is by using ViewContainerRef class from @Angular/core.

What you have to do is to declare a directive that will implement ViewContainerRef and act like a placeholder on your DOM.

Directive

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

@Directive({
  selector: '[appInject]'
})
export class InjectDirective {

  constructor(public viewContainerRef: ViewContainerRef) { }

}

Then, in the template where you want to inject the component:

HTML

<div class="where_you_want_to_inject">    
  <ng-template appInject></ng-template>
</div>

Then, from the injected component code, you will inject the component containing the HTML you want:

import { Component, OnInit, ViewChild, ComponentFactoryResolver } from '@angular/core';
import { InjectDirective } from '../inject.directive';
import { InjectedComponent } from '../injected/injected.component';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {

  @ViewChild(InjectDirective) injectComp: InjectDirective;

  constructor(private _componentFactoryResolver: ComponentFactoryResolver) {
  }

  ngOnInit() {
  }

  public addComp() {
    const componentFactory = this._componentFactoryResolver.resolveComponentFactory(InjectedComponent);
    const viewContainerRef = this.injectComp.viewContainerRef;
    const componentRef = viewContainerRef.createComponent(componentFactory);
  }

  public removeComp() {
    const componentFactory = this._componentFactoryResolver.resolveComponentFactory(InjectedComponent);
    const viewContainerRef = this.injectComp.viewContainerRef;
    const componentRef = viewContainerRef.remove();
  }

}

I added a fully working demo app on Angular 2 dynamically add component to DOM demo

The below code will help you

myval you can replace with the desired html

<div [innerHTML]="myVal"></div>

If you have templates in your angular (or whatever framework) application, and you return HTML templates from your backend through a HTTP request/response, you are mixing up templates between the frontend and the backend.

Why not just leave the templating stuff either in the frontend (i would suggest that), or in the backend (pretty intransparent imo)?

And if you keep templates in the frontend, why not just respond with JSON for requests to the backend. You do not even have to implement a RESTful structure, but keeping templates on one side makes your code more transparent.

This will pay back when someone else has to cope with your code (or even you yourself are re-entering your own code after a while)!

If you do it right, you will have small components with small templates, and best of all, if your code is imba, someone who doesn't know coding languages will be able to understand your templates and your logic! So additionally, keep your functions/methods as small you can. You will eventually find out that maintaining, refactoring, reviewing, and adding features will be much easier compared to large functions/methods/classes and mixing up templating and logic between the frontend and the backend - and keep as much of the logic in the backend if your frontend needs to be more flexible (e.g. writing an android frontend or switching to a different frontend framework).

Philosophy, man :)

p.s.: you do not have to implement 100% clean code, because it is very expensive - especially if you have to motivate team members ;) but: you should find a good balance between an approach to cleaner code and what you have (maybe it is already pretty clean)

check the book if you can and let it enter your soul: https://de.wikipedia.org/wiki/Clean_Code

upvote
  flag
yes, i saw @TGHs answer :) – Guntram

Not the answer you're looking for? Browse other questions tagged or ask your own question.