Link compile html in ng-repeat

1.6k views Asked by At

I have been searching for hours on this problem, and I can't seem to wrap my mind around a solution here.

I am attempting to create a directive that should be able to render a functional bit of HTML. I thought that running the HTML through the $compile would be enough, but it appears that it's only going 1 level deep.

How do I compile the rawHtml portion of my data so that the ng-click works?

** Edit: I figured out how to use the angular sanitize to return the HTML, however, it's still not compiled. How do I compile this to the scope?

Plunker: http://plnkr.co/edit/f9nxHlbRThzSHoD3Awhp?p=preview

<body ng-app='testApp'>
  <div ng-controller='testCtrl'>
    <test-directive ng-model='dataItems'></test-directive>
  </div>
</body>      

and JS

var app = angular.module('testApp', ['ngSanitize']);

app.controller('testCtrl', ['$scope', function($scope) {
  $scope.dataItems = [
      { name: 'Test1', rawHtml: '<input type="button" ng-click="onClick(1);" value="Click 1" />' },
      { name: 'Test2', rawHtml: '<input type="button" ng-click="onClick(2);" value="Click 2" />' }
    ]
}]);

app.directive('testDirective', ['$compile', '$sce', function($compile, $sce) {
  return {
    restrict: 'E',
    scope: {
      ngModel: "="
    },
    template: "<ul><li ng-repeat='item in ngModel'><div ng-bind-html=\"getHtml(item.rawHtml)\">{{item.name}}</div></li></ul>",
    controller: function($scope) {
      $scope.onClick = function(num) {
        console.log(num);
      }

      $scope.getHtml = function(html) {
        return $sce.trustAsHtml(html); 
      }
    }
  }
}])
1

There are 1 answers

1
Valentyn Shybanov On

Actually you should try to avoid it as much as possible. It could be done in very rare cases and used extremely careful.

In AngularJS-way you should provide everything possible in view and don't put any view logic in JS code. You can include different templates, you can use ng-switch/ng-if to select one of the options.

But if you really need it, you can use $compile indeed. You can use directive for that:

app.directive('compile', function($compile) {
  return {
    restrict:'A',
    link: function(scope, element, attr) {
      element.append($compile(attr.compile)(scope));
    }
  }  
})

And use it as

<div compile="{{item.rawHtml}}">

Plunker: http://plnkr.co/edit/6vNg5fP5yfOsATmSkReg?p=preview

But USE IT WITH CAUTION. I would not recommend this directive for general purpose.