4

I am trying to bind the following json response in my html page. The json is as follows:

{
"key":{
"text":"<p>For more information, please visit  <a href = \"javascript:void(0);\" ng-click = \"customizeWindow('http://www.google.com');\">Support</a> .</p>"
}
}

html page

<div ng-bind-html="message"></div>

Controller Code

$http({
       method: 'GET',
       url:'DAYS.json'

     }).success(function(responsedata) {
        $scope.message=responsedata.key.text;
      }).error(function(responsedata){});

customizeWindow function inside controller

$scope.customizeWindow = function(url) {
        window.open(url, "_blank", "toolbar=yes, scrollbars=yes, resizable=yes,top=70, left=190, width=970, height=460");
    }

The ng-bind-html binds the html tags but it strips off the javascript and ng-click event. i get only Support when i inspect element and the link does not work.

Please suggest me a solution.

2 Answers2

2

This happens since angular Automatically uses $sce -> Strict Contextual Escaping. it allows you to ng-bind-html but it doesn't allow you to add possibly malicious code like JS. What you are after is explicitly trusting that segment as HTML.

therefore:

angular.module('app', ["ngSanitize"]) // You have to include ngSanitize or it wouldn't work.
.controller('Ctrl', function ($scope, $sce){

$scope.htmlData = <p>For more information, please visit  <a href = \"javascript:void(0);\" ng-click = \"customizeWindow('http://www.google.com');\">Support</a> .</p> //Took from your example.

$scope.$watch("htmlData", function(newValue){
$scope.trustedData = $sce.trustAsHtml(newValuew);
  });
});

HTML Usage:

<p ng-bind-html="trustedData"></p>

Angular Resource:

Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain contexts to result in a value that is marked as safe to use for that context. One example of such a context is binding arbitrary html controlled by the user via ng-bind-html. We refer to these contexts as privileged or SCE contexts.

As of version 1.2, Angular ships with SCE enabled by default.

read on : Angular on SCE - trustAsHtml method

Linial
  • 1,154
  • 9
  • 22
  • i am using ngSanitize to handle html content. but the issue is it does not bind the javascript function call. Only displays Support – user3861155 Oct 14 '14 at 15:54
  • SCE trustAsHtml will allow you to paste JS as long as you acknowledge that JSON to be trusted. Good Luck – Linial Oct 14 '14 at 16:09
  • Hey Thanks ! Yes it worked if i use onclick instead of ng-click. Do u have solution for binding ng-click events also and how to bind if we have something like {{value}} in the json response and $scope.value ='something based on calculation result' is received from the controller code. I may have have asked a weird question but i am new to angular js. But surely this is possible may be not with $sce but some other way like $compile. can you help me with this too please? – user3861155 Oct 17 '14 at 07:56
1

ng-bind-html content is sanitized by default and its not meant to bring DOM into the page. You would use this method to bring content onto the page. Eg if you have a rich text editor - you want to feed it html content, however sanitized and thats when you use ng-bind-html.

For your purpose I would suggest to use templates or plain model binding.

Source of your json, what ever that is should not really know anything about the consumer side (your page) implementation/technology what if you move away from angularJS and start using Knockout, you will have to change server-side as well, because Knockout will have no idea about ng-click. Just pass back the content like http://www.google.com, 'For more information, please visit' and bind it.

 {
        "key":{
        "textsource": { 
                              source :  'http://www.google.com',
                              message : 'For more information, please visit  ' 
                       }
        }
     }

    <p>{{textsource.message}}<div  ng-click="customizeWindow(textsource.source)\">Support</div> </p>

If you can't change server side, have a look at this example :

1) tell $sce your content is fine

 $scope.message = $sce.trustAsHtml(json.key.text);

2) recompile your dynamicaly added content

  $scope.init = function () {
            var el = document.getElementById("dynamic");
             $compile(el.childNodes[0])($scope);
        };

NOTE: the recompile step is manual for now (press the recompile button). Follow this to make it work nicely.

Community
  • 1
  • 1
Vojtiik
  • 2,558
  • 1
  • 17
  • 21
  • And what if he can't change the server side? – Linial Oct 14 '14 at 16:17
  • @Linial yes sometimes we can't change the server side and then it all gets interesting :) I have updated my answer - have a look at the fiddle ! And don't forget to press the recompile button - I don't have time to finish it off up to fully functional standard, but I guess you get the point. – Vojtiik Oct 15 '14 at 10:13
  • @user3861155 any progress with your issue ? Did you run my example does it work for you ? – Vojtiik Oct 16 '14 at 08:42