ng-click not working after compile ng-bind-html

18,226

You don't need to deal with $sce to meet your purpose.

You can pass your HTML as string to the directive. After compilation in the directive it'll work.

In HTML where you need the directive

<dir id="dir" content="myVal"></dir>

Set different value in myVal your controller

$scope.myVal = '<button ng-click=\'buttonClick()\'>I\'m button</button>'; // HTML as string

The directive

myApp.directive('dir', function($compile, $parse) {
    return {
      restrict: 'E',
      link: function(scope, element, attr) {
        scope.$watch(attr.content, function() {
          element.html($parse(attr.content)(scope));
          $compile(element.contents())(scope);
        }, true);
      }
    }
  })

Check the Demo

Share:
18,226
user1
Author by

user1

My name is Iliya Idakiev and I'm a Google Developer Expert (GDE). I'm also a software developer/entrepreneur, as well as a JavaScript enthusiast with 7+ years experience in software development for the web. I'm is а co-organiser of Angular Sofia, commit.js, SofiaJS / BeerJS and a lecturer at Sofia University (Faculty of Mathematics and Informatics). I also do a lot of private and public trainings and from time to time I work as consultant/contractor. My main focus now is developing the JavaScript community in my country (Bulgaria) and growing my company - https://hillgrand.com/ In my spare time I like collecting and playing vinyl on musical events.

Updated on June 29, 2022

Comments

  • user1
    user1 almost 2 years

    I have a directive

    app.directive("dir", function($compile, $sce){
          return{
            restrict: "E",
            link: function(scope, element, attr){
              scope.$watch('content',function(){
                var html = $sce.trustAsHtml(attr.content);
                scope.alabala = $compile(html)(scope);
              },true);
            },
            template: "<div ng-bind-html='alabala'></div>",
          }
        });
    

    a controller:

    function MainController($scope, $http, customService, $location, $sce, $compile){
        $scope.init = function(){
            customService.get().success(function(data) {
                     var html = $sce.trustAsHtml(data);
                    $("#dir").attr("content", data);
    
                });
        };
    }
    

    and on my index page I have:

    <div id="div" ng-controller="MainController" class="pull-right span3" ng-init="init()">
          <dir id="dir" ></dir>
    </div>
    

    my custom service returns every time a different html containing for example

    <button ng-click='click()'>Click me</button>
    

    What I am trying to do is every time when I push a different value in the content of my directive to compile it and put it in my html and handle the click function from my controller. Because I'm new to AngularJS I have been struggling with this problem for sometime. Please help.

  • user1
    user1 over 10 years
    Thank you so much!!! Works perfect! In the way I wrote it is the $sce the problem or Im not passing it the right way to the directive?
  • Vishnu Sureshkumar
    Vishnu Sureshkumar over 9 years
    @Reza - Could you please explain what $watch and $compile doing here. Would be happy if you could explain your code.
  • Tasnim Reza
    Tasnim Reza over 9 years
    Here $watch used for automatic rendering, it listening directive's content value if content changed then it works. If you think your directive works only single time then you don't need $watch. Here $parse used for parsing the string content and $compile will link newly generated HTML with scope.
  • mila
    mila about 9 years
    @Reza Can you please tell me how to pass a templateUrl into $scope.myVal? Thanks!
  • Tasnim Reza
    Tasnim Reza about 9 years
    @mila Here $scope.myVal is used to pass HTML Content as string NOT url. If you need to load a template then use directive's templateUrl like docs.angularjs.org/guide/directive#template-expanding-direct‌​ive
  • mila
    mila about 9 years
    Thank you @Reza but I'm not sure templateUrl is my way to go since I need to load the template dynamically.
  • Tasnim Reza
    Tasnim Reza about 9 years
    Then you can use templateUrl as function like function(elem, attr){ return 'customer-'+attr.type+'.html'; }. In your directive add a type attribute which indicate your template type and inside of function you can create your dynamic template url.