How to check if a method argument of a directive is specified in AngularJS?
Solution 1
Using '&?' returns undefined if the attribute has not been set.
'&' = callback function is defined always.
'&?' = callback function is defined only when attribute is defined in html template.
bindToController: {
callback: '&?'
},
controller: function() {
if (this.callback === undefined) {
// attribute "callback" was not defined
}
}
Note: Works in Angular 1.4.8. I'm not sure if it works in older versions.
Solution 2
Looking at angularjs source code, I see this:
case '&':
parentGet = $parse(attrs[attrName]);
isolateScope[scopeName] = function(locals) {
return parentGet(scope, locals);
};
break;
The parentGet
is the bound function expression. Unfortunately, this is a local variable which is only available to the function assigned to isolateScope[scopeName]
via closure.
Instead of trying to find a way to get that variable, a simple solution is just to check the attrs
. Try:
link: function(scope,elem,attrs) {
scope.hasCallback = function() {
return angular.isDefined(attrs.callback);
}
}
Ferenc T
Updated on August 08, 2022Comments
-
Ferenc T almost 2 years
I've created a custom directive which contains a button. This button calls a method from parent scope specified by 'callback' attribute.
<!DOCTYPE html> <html ng-app="app"> <head> <title>Simple directive</title> <script src="js/lib/angular/angular.js"></script> <script type="text/javascript"> var app = angular.module('app', []); app.controller('TestController', function($scope) { $scope.doSomething = function(param) { alert('Something called with: ' + param); } }) app.directive('myDirective', function() { var ret = { restrict: 'E', scope: { user: '@', callback: '&' // bound a function from the scope }, template: '<div>Hello {{user}}<button ng-show="hasCallback()" ng-click="callback({userData: user})">Callback</button>', controller: function($scope) { $scope.hasCallback2 = function() { var t = typeof $scope.callback; return t == 'function'; } $scope.hasCallback = function() { return angular.isDefined($scope.callback); } } }; return ret; }); </script> </head> <body ng-controller="TestController"> <my-directive user="cat" callback="doSomething(userData)"></my-directive> <my-directive user="dog" callback="doSomething(userData)"></my-directive> <my-directive user="pig"></my-directive> </body> </html>
My question is:
How can I control visibility of button inside template? I'd like to hide it if callback attribute not specified in custom tag (see 3rd my-directive tag). When I check typeof of callback, I always get 'function' and angular.isDefined(...) also returns true.
-
Rebecca about 8 yearsThis worked perfectly and is a much more elegant solution. Should be the correct answer.
-
fracz almost 8 yearsThere is not a single word about it in the docs.
-
noherczeg almost 8 yearsThis does not work in 1.3.18, it always wires in a wrapper function no matter if it is defined in the DOM or not.
-
vip about 7 yearsDocs: docs.angularjs.org/api/ng/service/$compile Directive Definition Object -> scope section
-
Stalinko about 7 yearshelped me, but instead of
angular.isDefined
I prefer vanilla-jsattrs.hasOwnProperty('callback');
-
Khanh TO about 7 years@Stalinko: if you want to use vanila-js for some reason, a simple check for
undefined
should work:if (typeof attrs.callback === "undefined")