<!DOCTYPE html>
<html>

  <head>
    <script data-require="angular.js@1.2.21" data-semver="1.2.21" src="https://code.angularjs.org/1.2.21/angular.js"></script>
    <link data-require="bootstrap-css@*" data-semver="3.2.0" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-app="btnExample">
    
    <div ng-controller="SolutionOneCtrl">
      <h3>Solution 1:</h3>
      <h4>Use angular directives [ngClick + ngDisabled]</h4>
      <button class="btn btn-primary" ng-click="refreshOne()" ng-disabled="myDataOne.isRefreshing">Refresh</button>
      <span>{{ myDataOne.message }}</span>
    </div>
    
    <div ng-controller="SolutionTwoCtrl">
      <h3>Solution 2:</h3>
      <h4>Use custom directive [disableOnPromise], better way</h4>
      <button class="btn btn-primary" disable-on-promise="refreshTwo()">Refresh</button>
      <span>{{ myDataTwo.message }}</span>
    </div>
    
    
  </body>

</html>
var app = angular.module('btnExample', []);

app.controller('SolutionOneCtrl', function($scope, Data) {
  
  $scope.myDataOne = {
    isRefreshing: false,
    message: ''
  };
  
  $scope.refreshOne = function() {
    $scope.myDataOne.isRefreshing = true;
    $scope.myDataOne.message = 'refresh in progress';
    
    Data.refresh().then(
      function(data) {
        $scope.myDataOne.message = 'Data received, show it now..';
      },
      function(error) {
        $scope.myDataOne.message = 'Error..';
      }
    ).finally(
      function() {
        $scope.myDataOne.isRefreshing = false;
      });
  };
  
});


app.controller('SolutionTwoCtrl', function($scope, Data) {
  
  $scope.myDataTwo = {
    message: ''
  };
  
  $scope.refreshTwo = function() {
    $scope.myDataTwo.message = 'refresh in progress';
    
    return Data.refresh().then(
      function(data) {
        $scope.myDataTwo.message = 'Data received, show it now..';
      },
      function(error) {
        $scope.myDataTwo.message = 'Error..';
      });
  };
});


app.factory('Data', function($q, $timeout) {
  return {
    refresh: function() {
      // Simulate an http request:
      var deferred = $q.defer();
      $timeout(function() { deferred.resolve("Good!"); }, 3000);
      return deferred.promise;
		  
      // In real case, something like that:
      // return Restangular.getList('something');
    }
  };
});


app.directive('disableOnPromise', function ($parse) {
    return {
		restrict: 'A',
		compile: function($element, attr) {
			var fn = $parse(attr.disableOnPromise);
			return function clickHandler(scope, element, attrs) {
				element.on('click', function(event) {
					attrs.$set('disabled', true);
					scope.$apply(function() {
						fn(scope, {$event:event}).finally(function() {
							attrs.$set('disabled', false);
						});
					});
				});
			};
		}
	};
});
/* Styles go here */

body {
  margin: 50px;
}