Search code examples
javascriptangularjsangularjs-digest

How can I digest my Angular directives inside my sanitized HTML string? | AngularJS


I'm having trouble recompiling Angular code found in my $scope.content object after it is inserted to the DOM via ng-bind-html-unsafe. Anyone know how to have Angular digest this code? Thanks a ton in advance!

PLUNKER HERE.

###index.html###
<body ng-controller="MainCtrl">
 <h2>HTML Testing</h2>
 <div ng-bind-html-unsafe="content.iPhone"></div>
</body>

###app.js###
var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.content = {
    iPhone: "<div ng-style=\"style.iPhoneTest\">This shows up on an iPhone</div>",
    iPad: "<div ng-style=\"style.iPadTest\">This shows up on an iPad</div>",
    androidPhone: "<div ng-style=\"style.androidPhoneTest\">This shows up on an Android          phone</div>",
    androidTablet: "<div ng-style=\"style.androidPhoneTablet\">This shows up on an Android tablet</div>"
  };
  $scope.style = {
    iPhoneTest: {background: 'blue', color: 'black'},
    iPadTest: {background: 'black', color: 'white'},
    androidPhoneTest: {background: 'yellow', color: 'black'},
    androidTabletTest: {background: '#111', color: 'white'}
  };
});

Solution

  • Why not using a directive instead of injecting ?

    <body ng-controller="MainCtrl">
     <h2>HTML Testing</h2>
     <div ng-my-phones="style"></div>
    </body>
    
    app.directive("ngMyPhones", function(){
     return {
       scope: {
        "style": "=ngMyPhones"
       },
       template: '<div ng-style=\"style.iPhoneTest\">This shows up on an iPhone</div>'+
    '<div ng-style=\"style.iPadTest\">This shows up on an iPad</div>'+
    '<div ng-style=\"style.androidPhoneTest\">This shows up on an Android phone</div>'+
    '<div ng-style=\"style.androidPhoneTablet\">This shows up on an Android tablet</div>'
     }
    });
    

    Otherwise you have to use $compile, to tell angular to apply the scope on custom html, but this is a ugly approach.

    If you want dynamically decide which phone to show, you may pass the $scope.contents array into the directive, $compile and append the element by hand like this:

    <body ng-controller="MainCtrl">
           <h2>HTML Testing</h2>
           <div ng-my-phone="content.iPhone" ng-my-phone-style="style"></div>
         </body>
    </html>
    
    
     app.directive("ngMyPhone", function($compile){
      return {
        scope: {
          "ngMyPhone": "=",
          "style": "=ngMyPhoneStyle"
        },
        link: function($scope, $element){
           var oldPhoneElement; 
    
           //Everytime the phone
           $scope.$watch("ngMyPhone", function(newContent){
             angular.element(oldPhoneElement).remove();
             oldPhoneElement = angular.element(newContent);
    
             $compile(oldPhoneElement)($scope);
             $element.append(oldPhoneElement);
           });
        }
      };
    });
    

    WORKING PLUNKER