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.
Inside the directive it is creating an updateMap() method on the scope object in the directive and then calling the setFn() method which is mapped to the $scope. setDirectiveFn() method by this line: <map set-fn="setDirectiveFn(theDirFn)"></map> in your HTML and this line: scope: { setFn: '&' } in your directive.
Overview. Compiles an HTML string or DOM into a template and produces a template function, which can then be used to link scope and the template together. The compilation is a process of walking the DOM tree and matching DOM elements to directives.
ng-app: The ng-app Directive in AngularJS is used to define the root element of an AngularJS application. This directive automatically initializes the AngularJS application on page load. It can be used to load various modules in AngularJS Application.
The ng-app directive defines the root element of an AngularJS application. The ng-app directive will auto-bootstrap (automatically initialize) the application when a web page is loaded.
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.
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); } }
DEMO
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With