Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
154 views
in Technique[技术] by (71.8m points)

javascript - ng-bind-html or ngSanitize not working

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Use this somewhere in your controller:

// uses js machinery to decode HTML
function decodeHtml(html) {
  var txt = document.createElement("textarea");
  txt.innerHTML = html;
  return txt.value;
}

var encodedHtml = '&lt;!-- SC_OFF --&gt;&lt;div class="md"&gt;&lt;p&gt;Can be drugs, but also things like TV, games, sex, etc&lt;/p&gt; &lt;/div&gt;&lt;!-- SC_ON --&gt;';
$scope.html = decodeHtml(encodedHtml);

and in your template:

<p>{{html}}</p>

Demo


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...