1

I have a simple directive that passes a function on to a plugin; the plugin will then use the function with a given value. For simplicity, let's ignore changes on the data:

angular.module('some.directives', [])
  .directive('myDirective', [,
    function () {
      return {
        restrict: 'EAC',
        scope: {
          value: '@', // some value
          fun: '&' // the function
        },
        link: function(scope, element, attrs) {
          ThePlugin.thisIsTheVal(scope.value);
          ThePlugin.thisIsTheFun(scope.fun);
        }
      };
    }
  ]);

The problem is: when the fun attribute is not defined or the parent scope doesn't have the specified function, ThePlugin will always execute angular.noop, as that seems to be the default AngularJS provides.

Since I need to pass a real undefined when the function is not defined, how can I know if the calling scope actually has the function?

A workaround may consist in testing the function against the target value, and then return undefined if the resulting value is undefined itself:

ThePlugin.thisIsTheFun(function() {
  if (scope.fun(scope.value) === undefined) {
    return scope.fun;
  }
  return undefined;
});

This may lead to some inconsistencies, since it may be that the fun function will be allowed to return undefined as a proper result in the future.

5
  • Try this: ThePlugin.thisIsTheFun(scope.fun !== angular.noop ? scope.fun : undefined). Maybe it's the same noop function (haven't tested) Commented May 15, 2014 at 9:23
  • The thing is, scope.fun is never (directly) equal to angular.noop but it returns a parentGet(scope, locals) that would later be evaluated to the target function in the caller scope. I have also tried to check $parse(attrs['fun']) === angular.noop but this only works when the attribute is not set and not, for example, when the attribute is set but the function is not found. Commented May 15, 2014 at 9:27
  • 1
    Oh, yeah. You are absolutely right! It is actually a function that "wraps" the expression that is given in the template. BTW, a colleague was complaining about this thing where he wanted to behave like "if the function is given, do this, otherwise do something else" in order to be more "flexible" in the way the directive was used. We realized that the overall design was more complex than it should have been and re-thought the whole thing. Commented May 15, 2014 at 9:52
  • I agree, but in my case the design does not depend on my decisions, since I am integrating with an external plugin. Commented May 15, 2014 at 10:03
  • For me it worked using scope.fun = (attrs.hasOwnProperty('fun') ? scope.fun : undefined); Maybe a later version of angular has "fixed" this? :) Cause I had this exact issue.. Commented Feb 5, 2015 at 20:07

1 Answer 1

1

Check if the fun attribute is defined:

if (!attrs.hasOwnProperty('fun')) {
   scope.fun = undefined;
}
Sign up to request clarification or add additional context in comments.

6 Comments

I have specified in the second comment to the question that "I have also tried to check $parse(attrs['fun']) === angular.noop but this only works when the attribute is not set and not, for example, when the attribute is set but the function is not found.".
@frapontillo Why would the expression contain an undefined function? And even if: Why should the directive care? It's an error condition after all.
There are three possibilities: 1) the attribute is not set, therefore the function will be resolved to angular.noop, 2) the attribute is set and the function exists, 3) the attribute is set but the function does not exist.
@frapontillo got that, but 3 doesn't make sense to me and I still don't know why the directive should care. I would only write <my-directive fun="x()"> if x actually existed, wouldn't I? I wouldn't call x if I knew it doesn't exist.
Of course, but that happens in an ideal world; there might be a syntax error, or the function may have not been defined yet, so the directive would want to handle the particular case.
|

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.