I am trying to display some data from a JSON query, including a string of HTML content in my AngularJS app (using Angular 1.2.15, Angular-Sanitize 1.2.16, Yeoman 1.0). I've tried everything I can find to get ng-bind-html to work, but it always prints the HTML tags with the content.
Here's an example of a string my JSON query gives me:
<!-- SC_OFF --><div class="md"><p>Can be drugs, but also things like TV, games, sex, etc</p> </div><!-- SC_ON -->
Here's what ng-bind-html prints:
<!-- SC_OFF --><div class="md"><p>Can be drugs, but also things like TV, games, sex, etc</p> </div><!-- SC_ON -->
Interestingly, if I copy the string that ng-bind-html outputs, save it as a string, and run it through $sce.trustAsHtml() and ng-bind-html again, it looks perfect. Unfortunately, I'm not quite sure how I'd go about doing that. Anyway, here's my code. I hope someone finds something I've missed. This is killing me.
Here's my controller:
angular.module('finalApp')
...other controllers here...
.controller('ModalCtrl', function ($scope, $modalInstance, $sce, post) {
$scope.post = post.data;
$scope.body = $sce.trustAsHtml($scope.post.selftext_html);
...
});
I'm displaying the content in an Angular Bootstrap Modal window, so I pass in the post object from another controller which takes care of the JSON query.
My view:
<div ng-controller="MainCtrl">
<div class="modal-top">
<button class="btn btn-warning pull-right" ng-click="close()" style="margin:10px;">X</button>
</div>
<div class="modal-header">
<h3 class="modal-title">{{post.title}}</h3>
<h5 class="">{{post.author}}</h5>
</div>
<div class="modal-body">
<span ng-bind-html="body"></span>
</div>
</div>
My app.js:
angular.module('finalApp', [
'ngResource',
'ngRoute',
'ui.bootstrap',
'ngSanitize'
]) ...
My scripts included in index.html:
<!-- build:js scripts/vendor.js -->
<!-- bower:js -->
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
<!-- endbower -->
<!-- endbuild -->
<!-- build:js({.tmp,app}) scripts/scripts.js -->
<script src="scripts/app.js"></script>
<script src="scripts/controllers/main.js"></script>
<!-- endbuild -->
<!-- build:js scripts/modules.js -->
<script src="bower_components/angular-resource/angular-resource.js"></script>
<script src="bower_components/angular-cookies/angular-cookies.js"></script>
<script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<!-- endbuild -->
Update
I wasn't having much success doing things correctly, so I decided to try running the string through $sce.trustAsHtml and ng-bind-html twice with a directive. It's ugly, but it works.
Controller:
.controller('ModalCtrl', function ($scope, $modalInstance, $sce, $sanitize, post) {
$scope.post = post.data;
$scope.decodeHtml = function(html) {
return $sce.trustAsHtml(html);
};
$scope.html = $sce.trustAsHtml($scope.post.selftext_html);
$scope.close = function(){
$modalInstance.dismiss();
};
});
View:
<div ng-controller="MainCtrl">
<div class="modal-top">
<button class="btn btn-warning pull-right" ng-click="close()" style="margin:10px;">X</button>
</div>
<div class="modal-header">
<h3 class="modal-title">{{post.title}}</h3>
<h5 class="">{{post.author}}</h5>
</div>
<div class=”modal-body”>
<!-- holds first pass output, then hidden -->
<span id="correct" ng-bind-html="html"></span>
<!-- holds final output -->
<div ng-bind-html="body"></div>
<!-- exists to process html with directive -->
<hello-world></hello-world>
</div>
</div>
Directive:
.directive('helloWorld', ['$timeout', function (timer) {
/* Note the injection of the $timeout service */
return {
scope: true,
restrict: 'AE',
replace: 'true',
template: '<p ng-bind-html="body"></p>',
link: function (scope, elem, attrs, ctrl) {
var hello = function () {
var s = elem.parent().find('span').text();
scope.body = scope.decodeHtml(s);
elem.parent().find('span').hide();
};
timer(hello, 0);
}
};
}]);
See Question&Answers more detail:
os