Reputation: 509
I just wrote this simple directive to show a spinner on my button while something remote is happening: http://plnkr.co/edit/rAJ4X7A3iidmqUD2M63A?p=preview
html:
<!DOCTYPE html>
<html ng-app="app">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="myController as vm">
<button ng-click="vm.saveAction()" class="btn btn-primary" type="button">
<!-- Original template -->
<i class="fa fa-floppy-o" ng-hide="vm.save"></i>
<i class="fa fa-circle-o-notch fa-spin ng-hide" ng-show="vm.save"></i> Save
<!-- end -->
</button>
<button ng-click="vm.removeAction()" class="btn btn-default" type="button">
<!-- Desired template (directive) -->
<i my-spinner="vm.remove" icon="fa fa-trash"></i> Remove
<!-- end -->
</button>
</body>
</html>
js:
app = angular.module('app', []);
app.controller('myController', ['$timeout', function($timeout) {
var vm = this;
vm.save = false;
vm.remove = false;
vm.saveAction = function() {
vm.save = true;
// ...save something remote
$timeout(function() { // <-- simulate an async callback or whatever...
vm.save = false;
}, 3000);
};
vm.removeAction = function() {
vm.remove = true;
// ...remove something remote
$timeout(function() { // <-- simulate an async callback or whatever...
vm.remove = false;
}, 3000);
};
}]);
app.directive('mySpinner', function() {
var directive = {
restrict: 'A',
scope: {
mySpinner: '@',
icon: '@'
},
template: '<i class="{{icon}}" ng-hide="{{mySpinner}}"></i>' +
'<i class="fa fa-circle-o-notch fa-spin ng-hide" ng-show="{{mySpinner}}"></i>',
};
return directive;
});
I decided to use this solution based on ng-show and ng-hide so I haven't to $observe/$watch nothing in my directive... The html from the directive seems right but when I press on the Remove button nothing happens. Someone could help me? Thank you very much!
Upvotes: 0
Views: 169
Reputation: 136144
You need to pass the value of mySpinner
using =
(two way binding) instead of @
(one way binding), The reason behind this is, as you using @
means you will pass value through attribute with interpolation {{}}
directive, which will eventually converts bool
to string
and the ng-show
expression value will always become true.
The other reason behind it was not working is you were using {{}}
interpolation in ng-show
& ng-hide
directive.
Directive
app.directive('mySpinner', function() {
var directive = {
restrict: 'A',
scope: {
mySpinner: '=',
icon: '@'
},
template: '<i class="{{icon}}" ng-hide="mySpinner"></i>' +
'<i class="fa fa-circle-o-notch fa-spin ng-hide" ng-show="mySpinner"></i>',
};
return directive;
});
You could refactor you template to use ng-class
instead of using ng-show
& ng-hide
by applying classes conditionally.
template: '<i ng-class="mySpinner ? \'fa fa-circle-o-notch fa-spin=\': icon"></i>'
Upvotes: 1