1

I'm attempting to build dynamic HTML strings which include a directive that reacts to changes in a scope variable. If I build the strings statically then my $watch works properly, but if the strings are dynamic then the $watch never fires.

I am sure the answer lies somewhere in use of $compile, and I have studied numerous examples, but I can't seem to make them work for my specific needs.

Is this possible?

My plunkr, which demonstrates referencing sentences with a superscript tag.

index.html

<body ng-controller="MainCtrl">
    <h3>Static Example</h3>
    <div>Humpty Dumpty sat<ref><sup>1</sup></ref> on a wall.</div>
    <div>Humpty Dumpty had a great<ref><sup>2</sup></ref> fall.</div>

    <h3>Dynamic Example</h3>
    <div ng-repeat="item in dynamic">
      <span ng-bind-html="item | to_trusted"></span>
    </div>
    <br>
    <input type="checkbox" ng-click="sup = !sup"> hide/show
</body>

app.js

var app = angular.module('app', [])
  .filter('to_trusted', ['$sce', function($sce) {
    return function(text) {
      return $sce.trustAsHtml(text);
    };
}]);

app.controller('MainCtrl', function($scope) {
  $scope.sup = true;
  $scope.dynamic = ["Humpty Dumpty sat on a wall.<ref><sup>1</sup></ref>", 
                    "Humpty Dumpty had a great fall.<ref><sup>2</sup></ref>"];
});

app.directive('sup', function($compile) {
  return {
    restrict: 'E',
    link: function(scope, element) {
      scope.$watch('sup', function() {
        element.css({ display: scope.sup ? 'inline' : 'none' });
      });
    }
}});
ScottD
  • 145
  • 1
  • 10
  • I don't know if this is any related but I think this could be useful http://stackoverflow.com/questions/26447885/how-directives-are-invoked-if-an-element-that-contains-a-directive-is-added-dyna – Michail Michailidis Oct 20 '14 at 17:54
  • @KevinB Fair enough. – ScottD Oct 20 '14 at 18:14
  • possible duplicate of [angular ng-bind-html-unsafe and directive within it](http://stackoverflow.com/questions/17417607/angular-ng-bind-html-unsafe-and-directive-within-it) – Kevin B Oct 20 '14 at 18:19
  • Note, the answer in the duplicate suggests making a directive to replace ng-bind-html, that's a directive separate from the one you already have. – Kevin B Oct 20 '14 at 18:21
  • 1
    Here's the updated plunkr: http://plnkr.co/edit/8jKORTChVvJSdxbUxFTq?p=preview (i ended up using a different answer than the selected one.) – Kevin B Oct 20 '14 at 18:27

1 Answers1

1

You have to change your directive like below.

app.directive('compile', ['$compile', function ($compile) {
    return function (scope, element, attrs) {
        scope.$watch(
      function (scope) {
          return scope.$eval(attrs.compile);
      },
      function (value) {
          element.html(value);
          $compile(element.contents())(scope);
      }
    );
    };
}]);

then use it in html like this.

<h3>Dynamic Example</h3>
<div ng-repeat="item in dynamic">
  <span compile="item"></span>
</div>

Demo code

Seminda
  • 1,745
  • 12
  • 15