0

I've made a directive which uses element.html() to set the html. Inside that html-code I want to be able to call functions in the scope which the directive is used in. Something like this:

app.directive('myDirective', ['$rootScope', function ($rootScope) {
    return {
        restrict: 'A',
        link: function(scope, element) {
          element.html('<button ng-click="doit()">Does not work</button>');
        }
    };
}]);

The doit() function is never called though.

I made a plnkr to demonstrate it:

http://plnkr.co/edit/nckqny1FNiJJjthmlSh8?p=preview

3 Answers 3

1

When you're dynamically adding HTML, you have to manually compile and link it using the $compile service:

app.directive('myDirective', ['$compile', function ($compile) {
    return {
        restrict: 'A',
        link: function(scope, element) {
          var e = angular.element('<button ng-click="doit()">Works Now!!</button>');
          element.append(e);
          $compile(e)(scope);
        }
    };
}]);
Sign up to request clarification or add additional context in comments.

Comments

1

Why not just a template?

return {
    restrict: 'A',
    template:'<button ng-click="doit()">Do It</button>',
    link: function(scope, element, attrs) {

    }
};

2 Comments

This is what i was about to post. Its the correct way of doing using template:""
Most probably, the code is just an example. The HTML is determined dynamically "at rumtime".
0

Another approach is this:

return {
  restrict: 'A',
  template: '<button>Brings up alert</button><br><button>Does not work</button>',
  link:function(scope, element, attrs){
    element.on('click', function(e){
      if(e.target.nodeName.toLowerCase() == 'button'){
        scope.doit();
      }
    });
  }
};

instead of binding the click event inline like that in your code example you can bind the event in your linking function like as above, yet you need to do:

  1. Use template:"" option in the return of your directive.
  2. Bind event in your linking function.
  3. Current element is the div itself but you have to pass the event in the function args.
  4. Check if the clicked target is button with e.target.nodeName
  5. e.target.nodeName results the tagName in upperCase so use as in the if condition above.
  6. If the clicked element is button execute the scope.doit();

1 Comment

-1 Guess what, there is already a directive for that. How was it called again...oh, right...it's ngClick !

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.