<div ng-app="myApp" class="container">  
  <div ng-controller="mainController as vm" class="row">
    <div class="col-xs-12">
      <label>Email
        <input type="email" ng-model="vm.email" />
      </label>
      <button ng-click="vm.click()">Check</button>
      <p ng-bind="vm.result"></p>      
    </div>
  </div>
  <div ng-controller="historyController as vm" class="row">
    <ul class="list-group col-xs-12">
      <li ng-repeat="(email,state) in vm.emails" ng-bind="email" ng-class="vm.cls(state)"></li>
    </ul>
  </div>
</div>
body { 
  padding-top:20px;
}
angular.module('myApp', []);


angular.module('myApp').factory('EmailChecker', HaveIBeenPwned);
angular.module('myApp').controller('mainController', ['$scope', 'EmailChecker', MainController]);
angular.module('myApp').controller('historyController', ['EmailChecker', HistoryController]);

/**
* Service: HaveIBeenPwned
* Methods: check_email(email) -> Promise
* Variables: emails: [...]
* 
* The service is used to communicate with the external haveibeenpwned API
*/
HaveIBeenPwned.$inject = ['$http'];
function HaveIBeenPwned($http) {  
  var _emails = {};
  
  return {
    check_email: check_email,
    emails: _emails,
  };
  
  function check_email(email) {
    var self = this;
    
    return new Promise(function(resolve, reject) {
      var xhr = new XMLHttpRequest();
      var url = 'https://haveibeenpwned.com/api/v2/pasteaccount/' + email;
      $http.get(url).then(function(res) {
        self.emails[email] = "Leaked";
        resolve(res.data[0].Source + "/" + res.data[0].Id);
      }, function() {
        resolve("Safe");
        self.emails[email] = "Safe";
      });
    });
  }
}

/**
* MainController uses the service to check email addresses 
*/
function MainController($scope, EmailChecker) {
  var vm = this;
  this.email = "";
  this.click = function() {
    if ( this.email.length === 0 ) {
      alert('Empty email');
      return;
    }
    
    EmailChecker.check_email(this.email).then(function(msg) {      
      // note the call to $scope.$apply:
      // After assigning to vm.result variable we need to let
      // angular know something has changed so the UI can be rendered
      $scope.$apply(function() {
        vm.result = msg;
      });
    });        
  };
}

/**
* A history controller connects the list of emails to the view. Note
* that it needs very little to operate correctly, because every time
* the list changes a $scope.$apply called is already performed from 
* another controller.
*/
function HistoryController(EmailChecker) {
  var vm = this;
  vm.foo = "bar";
  vm.emails = EmailChecker.emails;
  
  vm.cls = function(state) {
    if ( state === "Leaked" ) {
      return "list-group-item list-group-item-danger";
    } else {
      return "list-group-item list-group-item-success";
    }
  }
}

External CSS

  1. //maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.3/angular.min.js