68

This is my template:

<div class="span12">
  <ng:view></ng:view>
</div>

and this is my view template:

<h1>{{stuff.title}}</h1>

{{stuff.content}}

I am getting the content as html and I want to display that in a view, but all I am getting is raw html code. How can I render that HTML?

Ben Thomas
  • 3,180
  • 2
  • 20
  • 38
user194932147
  • 963
  • 2
  • 8
  • 13
  • 2
    Where is the HTML coming from? Under different circumstances, you'll want `ngBindHtmlUnsafe`, `ngSanitize`, or a custom directive. – Josh David Miller Apr 02 '13 at 01:14
  • The html is coming from my database – user194932147 Apr 02 '13 at 01:37
  • 1
    Is the content *absolutely* trusted? – Josh David Miller Apr 02 '13 at 01:41
  • @JoshDavidMiller can you please explain more about trusted. i mean i am entring the data myself but i would like to know what are the worst case scenarios – user194932147 Apr 02 '13 at 01:53
  • 1
    For example, if the HTML contains a `script` tag the browser would execute it. This type of "injection" attack is a common way of damaging apps and stealing user data. AngularJS has a separate module called `ngSanitize` that you can use to strip the HTML of any dangerous tags; it also has a directive called [`ngBindHtml`](http://docs.angularjs.org/api/ngSanitize.directive:ngBindHtml) that works just like `ngBindHtmlUnsafe`, but strips the dangerous tags for you. If the content is entirely yours - and doesn't come from users or third parties - then you don't need it. – Josh David Miller Apr 02 '13 at 03:45
  • Oh, and if you're pulling templates from a server, `ngInclude` or a (simple!) custom directive would probably be the better way to go. – Josh David Miller Apr 02 '13 at 03:46
  • 1
    possible duplicate of [Insert HTML into view using AngularJS](http://stackoverflow.com/questions/9381926/insert-html-into-view-using-angularjs) – kontur Oct 03 '14 at 13:42

5 Answers5

100

Use-

<span ng-bind-html="myContent"></span>

You need to tell angular to not escape it.

Pyrolistical
  • 27,624
  • 21
  • 81
  • 106
Jason
  • 15,915
  • 3
  • 48
  • 72
  • It's a typo - he meant ``. – Josh David Miller Apr 02 '13 at 01:40
  • 10
    API has changed in AngularJS 1.2. http://stackoverflow.com/questions/18340872/how-do-you-use-sce-trustashtmlstring-to-replicate-ng-bind-html-unsafe-in-angu – Alex M Dec 04 '13 at 18:00
  • 2
    amccausl has saved new angular users countless hours of debugging due to angular "hell docs", ng-bind-html-unsafe is deprecated and please refer to the link located in the comment above to solve the answer. – rjm226 Dec 16 '13 at 22:28
  • 1
    I just inserted into my template and without doing anything else it worked great. I didn't have to inject $sce. Here's the docs: https://docs.angularjs.org/api/ng/directive/ngBindHtml – Joseph Sheedy Feb 09 '15 at 20:47
  • 1
    ngSanitize -one thing that was missing for me when using the answers here(you can get from the angular docs on ng-bind-html) is you need to make sure your app includes the ngSanitize module. Without that it did not work. – jamie Aug 11 '15 at 22:06
  • 1
    `ng-bind-html` alone worked, without using `trustAsHtml` – Marco Lackovic Aug 08 '17 at 08:04
  • 1
    @MarcoLackovic this function makes sure to avoid html exploits see [here](https://docs.angularjs.org/api/ng/service/$sce) – Abr001am Nov 11 '17 at 16:08
50

To do this, I use a custom filter.

In my app:

myApp.filter('rawHtml', ['$sce', function($sce){
  return function(val) {
    return $sce.trustAsHtml(val);
  };
}]);

Then, in the view:

<h1>{{ stuff.title}}</h1>

<div ng-bind-html="stuff.content | rawHtml"></div>
Daniel
  • 10,115
  • 3
  • 44
  • 62
4

In angular 4+ we can use innerHTML property instead of ng-bind-html.

In my case, it's working and I am using angular 5.

<div class="chart-body" [innerHTML]="htmlContent"></div>

In.ts file

let htmlContent = 'This is the `<b>Bold</b>` text.';
Ajay Gupta
  • 2,867
  • 23
  • 28
3

You shoud follow the Angular docs and use $sce - $sce is a service that provides Strict Contextual Escaping services to AngularJS. Here is a docs: http://docs-angularjs-org-dev.appspot.com/api/ng.directive:ngBindHtmlUnsafe

Let's take an example with asynchroniously loading Eventbrite login button

In your controller:

someAppControllers.controller('SomeCtrl', ['$scope', '$sce', 'eventbriteLogin', 
  function($scope, $sce, eventbriteLogin) {

    eventbriteLogin.fetchButton(function(data){
      $scope.buttonLogin = $sce.trustAsHtml(data);
    });
  }]);

In your view just add:

<span ng-bind-html="buttonLogin"></span>

In your services:

someAppServices.factory('eventbriteLogin', function($resource){
   return {
        fetchButton: function(callback){
            Eventbrite.prototype.widget.login({'app_key': 'YOUR_API_KEY'}, function(widget_html){
                callback(widget_html);
            })
      }
    }
});
martar
  • 448
  • 3
  • 9
2

So maybe you want to have this in your index.html to load the library, script, and initialize the app with a view:

<html>
  <body ng-app="yourApp">
    <div class="span12">
      <div ng-view=""></div>
    </div>
    <script src="http://code.angularjs.org/1.2.0-rc.2/angular.js"></script>
    <script src="script.js"></script>
  </body>
</html>

Then yourView.html could just be:

<div>
  <h1>{{ stuff.h1 }}</h1>
  <p>{{ stuff.content }}</p>
</div>

scripts.js could have your controller with data $scope'd to it.

angular.module('yourApp')
    .controller('YourCtrl', function ($scope) {
      $scope.stuff = {
        'h1':'Title',
        'content':"A paragraph..."
      };
    });

Lastly, you'll have to config routes and assign the controller to view for it's $scope (i.e. your data object)

angular.module('yourApp', [])
.config(function ($routeProvider) {
  $routeProvider
    .when('/', {
      templateUrl: 'views/yourView.html',
      controller: 'YourCtrl'
    });
});

I haven't tested this, sorry if there's a bug but I think this is the Angularish way to get data

irth
  • 1,696
  • 2
  • 15
  • 24
  • What if I want this same behavior but not depend on routeProvider? – Raphael Isidro Jul 01 '16 at 02:18
  • It's the same using ui-router, only it's $stateProvider instead of $routeProvider and .state( 'yourState', { url:'/', templateUrl: 'yourView.html', controller: 'YourCtrl' }); – irth Jul 01 '16 at 23:17