0

I've got a pretty simple directive that I'd like to be able to run a callback with parameters supplied by the directive and the scope. For example:

<div ng-repeat="user in users">
  <div sample="..." callback="welcome(user, $message)">
  </div>
</div>

I'm having trouble using $parse to handle this. My sample directive is as follows:

app.directive('sample', ['$parse', function ($parse) {
  return {
    restrict: 'A',
    scope: {},
    link: function (scope, element, attrs) {
      // ...
      function greet () {
        var callback = $parse(attrs.callback);
        callback(scope, { $message: 'Howdy' });
      }
    },
  },
}]);

However, despite getting a function from $parse - executing the function never results in my welcome function (defined in a controller) being called (note: on Angular 1.5.x). I'm assuming scope is wrong somehow (that it is using the isolated scope instead of the parent scope) - but I do need an isolated scope (simplified for example). What am I doing wrong?

Stussa
  • 3,375
  • 3
  • 24
  • 35
  • Are you sure you need `$parse` and a directive in general? If this is for one controller, you could define `$scope.greet` in the controller. – Kris Molinari Feb 20 '17 at 23:38
  • The directive is used for multiple controllers and the 'callback' has different parameters (and optional '$message') in the definition for them (so not possible). – Stussa Feb 21 '17 at 06:07

2 Answers2

2

Can you use scope.$parent as a parameter to your $parse call? You may also wish to wrap with a $scope.$apply(function () { ... });.

Kevin Sylvestre
  • 37,288
  • 33
  • 152
  • 232
  • I don't think isolate scopes have access to any parent – Phil Feb 20 '17 at 23:35
  • 1
    @phil An isolated scope's $parent always refs a parent scope. Isolated means it doesn't inherit prototypically from a parent scope - *NOT* that $parent isn't defined. – Kevin Sylvestre Feb 21 '17 at 06:14
0

You may use the & isolate scope binding. I'd also provide the user object to your directive

return {
  restrict: 'A',
  scope: {
    user: '<',
    callback: '&'
  }
  link: function(scope) {
    // ...
    function greet() {
      scope.callback({
        user: scope.user,
        $message: 'Howdy'
      })
    }
  }
}

and

<div sample="..." user="user" callback="welcome(user, $message)">
Phil
  • 157,677
  • 23
  • 242
  • 245
  • This solution adds pretty strong coupling between the user and the directive (I'm trying to avoid and make the directive as generic as possible). I'm aiming for a directive much closer to the likes of `ng-click` - where the directive fills in some key parameters - but otherwise doesn't need to know about the outside happenings. I ideally need to support things like: `callback="welcome()"` and `callback="welcome(user)"` and `callback="welcome(item, $message)"` and `callback="welcome(item, user, $message)"`. – Stussa Feb 21 '17 at 06:10
  • @Stussa it's not tight coupling, it simply becomes part of the directive's API. In any case, I'm glad you found a solution that works for you – Phil Feb 22 '17 at 01:56