Search code examples
javascriptangularjsusing-directives

Angular: function call as attribute value for directive


This is a reduction of my directive:

app.directive('myDirective', function() {
  return {
    restrict: 'E',
    replace: true,
    template:
      '<form name="form" action="{{action}}" method="post" target="_blank">' +
        '<input type="hidden" name="item_name" value="{{itemname}}">' +
      '</form>',
    scope: {
      action: '@action',
      itemname: '@itemname',
    },
    link: function(scope, element, attrs) {
      scope.action = attrs.action || 'http://www.example.com';
      scope.itemname = attrs.itemname();
    }
  };
});

and I use it this way:

<div ng-if="itemWasSelected">
  <my-directive
     action="{{ 'http://www.example.com' }}"
     itemname="itemNameBuildFunction"
  />
</div>

In my controller, I have:

$scope.itemNameBuildFunction = function() {
  return $scope.value1 + $scope.value2;
};

I would expect my directive, when it is linked (it is inside an ng-if clause, so, I mean, when the ng-if condition evaluates to true), to call attrs.itemname() $scope function, to assign scope.itemname variable in the controller's link function.

Instead, what I get is the error:

TypeError: attrs.itemname is not a function

Can you please give me some directions? As you can see, I'm quite confused, with angular directives... :-(


Solution

  • You don't need this statement attrs.itemname().

    Your function reference passed in directive is bind to to the variable itemname on scope that is passed as first parameter in link function which isolated scope

    Just change the statement from

    scope.itemname = attrs.itemname();
    

    To :

    scope.itemname();  // this will call the function `itemNameBuildFunction`
    

    EDIT :

    You have used @ operator ofr binding function which is used in case passing primitive or object.You are passing function, so , you should use & operator,will evaluate as function.

    scope: {
          action: '@action',
          itemname: '&itemname',
        }
    

    EDIT 2: Yous should passed function itemNameBuildFunction() and not itemNameBuildFunction

    <my-directive action="{{ 'http://www.example.com' }}" 
        itemname="itemNameBuildFunction()" />
    

    Working Plunker