54

I'm wondering what's the way to do work this snippet:

//html
<div ng-app="app">
    <div ng-controller="AppCtrl">
        <a my-dir ng-repeat="user in users">{{user.name}}</a>
    </div>
</div>

//js
var app = angular.module('app', []);
app.controller("AppCtrl", function ($scope) {
    $scope.users = [{name:'John',id:1},{name:'anonymous'}];
    $scope.fxn = function() {
        alert('It works');
    };

})  
app.directive("myDir", function ($compile) {
    return {
        link:function(scope,el){
            el.attr('ng-click','fxn()');
            //$compile(el)(scope); with this the script go mad 
        }
     };
});

I know it's about the compile phase but I don't get the point so a short explanation would be very appreciate.

1

2 Answers 2

89

A directive which adds another directive to the same element:

Similar answers:

Here is a plunker: http://plnkr.co/edit/ziU8d826WF6SwQllHHQq?p=preview

app.directive("myDir", function($compile) {
  return {
    priority:1001, // compiles first
    terminal:true, // prevent lower priority directives to compile after it
    compile: function(el) {
      el.removeAttr('my-dir'); // necessary to avoid infinite compile loop
      el.attr('ng-click', 'fxn()');
      var fn = $compile(el);
      return function(scope){
        fn(scope);
      };
    }
  };
});

Much cleaner solution - not to use ngClick at all:

A plunker: http://plnkr.co/edit/jY10enUVm31BwvLkDIAO?p=preview

app.directive("myDir", function($parse) {
  return {
    compile: function(tElm,tAttrs){
      var exp = $parse('fxn()');
      return function (scope,elm){
        elm.bind('click',function(){
          exp(scope);
        });  
      };
    }
  };
});
Sign up to request clarification or add additional context in comments.

8 Comments

Any idea why this doesn't work when using ng-repeat and calling a function on the directive's controller? I've modified your plunker to show what I mean. Note that the method being called on click is now on the directives controller. Also note that the "This works" link which is not nested in an ng-repeat works while the others do not: plnkr.co/edit/Y4ADmznnDCZvuxJrcZQ0?p=preview
Removing "my-dir" messes up my CSS specification. Is there a workaround to that? Thanks
you could have my-dir-unloaded attr and replace it to my-dir (or to my-dir-loaded) so CSS will work while directive wont get into an infinite loop (just guessing, didn't try)
@Dinesh var fn = $compile(el, null, 1001); and keep my-dir attribute intact.
It's not correct to simply call $compile() on the same element currently being compiled, it would recompile other, unrelated directives that happen to have greater priorities.
|
2

You can try this:

<div ng-app="app">
    <div ng-controller="AppCtrl">
        <a my-dir ng-repeat="user in users" ng-click="fxn()">{{user.name}}</a>
    </div>
</div>

<script>
var app = angular.module('app', []);

function AppCtrl($scope) {
        $scope.users = [{ name: 'John', id: 1 }, { name: 'anonymous' }];
        $scope.fxn = function () {
            alert('It works');
        };
    }

app.directive("myDir", function ($compile) {
    return {
        scope: {ngClick: '='}
    };
});
</script>

1 Comment

Attribute is suppose to be added on the fly. Not from the template

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.