0

I have a template for my directive, which contains a scope variable called content:

<div class="directive-view">
    <span class="directive-header">My Directive</span>
    <span ng-bind-html="content"></span>
</div>

I have the following directive, which watches for changes to content and then compiles the element's contents:

(function () {
    "use strict";

    angular
        .module('myApp.myDirective', [])
        .directive("myDirective", myDirective);

    function myDirective($compile, $sce) {
        return {
            restrict: 'E',
            scope: {
            },
            templateUrl:'../partials/directives/my-directive.html',
            controller: function($scope) {
                $scope.testAlert = function(msg) { alert(msg) };
            },
            link: function (scope, element, attrs, ctrl) {

                scope.content = $sce.trustAsHtml('Initial value');

                scope.$watch(attrs.content, function(value) {
                    element.html(value);
                    console.log("Content changed -- recompiling");
                    $compile(element.contents())(scope);
                });

                scope.content = $sce.trustAsHtml('<button ng-click="testAlert(\'clicked!\')">Click</button>');
            }
        };
    }
})();

The directive renders the button element. However, the controller function testAlert() does not get called when the button element is clicked on.

Also, the $watch callback is called only once, after content is set to Initial value. The callback is not triggered after content is set to the button. (I would have thought that the callback is triggered when the value of attrs.content is changed.)

If I manually recompile the element:

$compile(element.contents())(scope);

the button element still does not trigger the testAlert function when clicked.

How do I correctly recompile the element contents, so that the correct bindings are made?

3
  • 1
    You $watch function watch on change attrs.content. And you change scope.content. Try this scope.$watch('content',function(){}); Commented Mar 5, 2016 at 10:19
  • @StepanKasyanenko one as the same thing, attrs.content will get value as content, it will not make any difference Commented Mar 5, 2016 at 10:36
  • It's make difference! See my answer. Trying change scope.$watch('content',...) on scope.$watch(attrs.content,...) and you will see that it make difference. Commented Mar 5, 2016 at 10:44

1 Answer 1

1

You do not need use $sce in this case. Use just $compile.

Live example on jsfiddle.

var myApp = angular.module('myApp', []);

myApp.controller('MyCtrl', function($scope) {
    $scope.name = 'Superhero';
		$scope.changeTEmplate = function(){
      $scope.cont = '<div><b>i\'m changed</b></div>';
    }
  })
  .directive("myDirective", function myDirective($compile) {
    return {
      restrict: 'E',
      scope: {content:"="},
      template: `<div class="directive-view">
    <span class="directive-header">My Directive</span>
    <span></span>
    </div>`,
      controller: function($scope) {
        $scope.testAlert = function(msg) {
          alert(msg)
        };
      },
      link: function(scope, element, attrs, ctrl) {
        scope.$watch('content', function(value) {
          var span = angular.element(element.find('span')[1]);
          span.html(value);
          console.log("Content changed -- recompiling",value);
            $compile(span)(scope);
        });
        scope.content = '<button ng-click="testAlert(\'clicked!\')">Click</button>';
      }
    };
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
  <div ng-controller="MyCtrl">
    Hello, {{name}}!
    <button ng-click="changeTEmplate()"> change Content</button>
    <my-directive content="cont"></my-directive>
  </div>
</div>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.