2015-09-04 2 views
0

У меня есть код ниже, который использует данные в массиве сотрудников для расчета оплаты сотрудниками.Как использовать данные API на заводе AngularJS

'use strict'; 
 
var app = angular.module('app', []); 
 
app.factory('staffFactory', function ($http) { 
 
    var staff = [ 
 
     {"id": "1","name": "Kate","rate": "10", "hours": "10"}, 
 
     {"id": "2","name": "John","rate": "20", "hours": "10"}, 
 
     {"id": "3","name": "Matt","rate": "15", "hours": "10"} 
 
    ]; 
 

 
    function calcPayInner(){ 
 
    var unique = {}, 
 
     distinct = [],pay = []; 
 
    for (var i in staff) { 
 
     if (typeof (unique[staff[i].id]) == "undefined") { 
 
      distinct.push(staff[i].id); 
 
     } 
 
     unique[staff[i].id] = unique[staff[i].id] || {pay:0}; 
 
     unique[staff[i].id].name = staff[i].name; 
 
     unique[staff[i].id].pay += (parseInt(staff[i].rate, 10) * parseInt(staff[i].hours, 10)); 
 
    } 
 

 
     for (var p in unique) { 
 
      pay.push([p, unique[p]]); 
 
      pay.sort(function (a, b) { 
 
       return (b[1].pay - a[1].pay); 
 
      }); 
 
     } 
 
     return pay; 
 
    } 
 
    var staffService = {}; 
 
    staffService.allStaff = function() { 
 
     return staff; 
 
    }; 
 

 
    staffService.CalcPay = function() { 
 
     return calcPayInner(); 
 
    }; 
 

 
    return staffService; 
 
}); 
 

 
    app.controller('MainCtrl', ['$scope', 'staffFactory', function ($scope, staffFactory) { 
 
     $scope.staff = staffFactory.allStaff(); 
 
     console.log($scope.staff); 
 
     $scope.CalcPay = staffFactory.CalcPay(); 
 
     $scope.keyPress = function(keyCode){ 
 
      $scope.CalcPay = staffFactory.CalcPay(); 
 
     };  
 
    }]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 
<div ng-app="app"> 
 
     <div ng-controller="MainCtrl"> 
 
      <table> 
 
      <tr><td>name</td><td>rate</td><td>hours</td></tr> 
 
      <tr ng-repeat="s in staff"> 
 
       <td>{{s.name}}</td> 
 
       <td><input ng-keyup="keyPress(s.rate)" ng-model="s.rate"></td> 
 
       <td><input ng-keyup="keyPress(s.hours)" ng-model="s.hours"></td> 
 
      </tr> 
 
      </table> 
 
      <table> 
 
      <tr><td>name</td><td>pay</td></tr> 
 
      <tr ng-repeat="b in CalcPay"> 
 
       <td>{{b.1.name}}</td> 
 
       <td>{{b.1.pay}}</td> 
 
      </tr> 
 
      </table>   
 
    </div> 
 
</div>

Это все работает, как предполагалось, однако сейчас я хочу, чтобы получить данные по персоналу от API вызова, а не жестко закодированных данных.

Я пробовал ниже. (see plnkr)

var staff = []; 
    var test = $http.get('staff.json') 
    .success(function(data) { 
     staff = data; 
     console.log(staff); 
    }); 

который, кажется, возвращает данные, как я могу видеть в моей консоли, но я не могу заставить его работать (возвращает пустой массив) с моей существующей функции.

Я также попытался завернуть функцию в. Окончательно после .success, но тогда моя функция станет неопределенной.

Как я могу использовать данные API в своих функциях на своей фабрике, чтобы я мог работать с моей страницей, поскольку она первоначально была с жестко закодированным массивом?

ответ

2

Проблема, как уже упоминалось, что вы пытаетесь получить данные, прежде чем он доступен. Решение проблемы состоит в том, чтобы использовать обещания внутри вашей фабрики, если вы хотите сохранить единый источник данных.

ниже код использует q, поэтому вам придется вводить его на завод.

app.factory('staffFactory', function ($http, $q) {} 

реализация allStaff

/* Private var to hold the staff */ 
var staff = []; 

// this method returns a promise 
staffService.allStaff = function() { 
    var deferred = $q.defer(); 

    // check if staff is already fetched from server if yes resolve the promise immediately 
    if (staff.length > 0) { 
     // we have data already. we can avoid going to server 
     deferred.resolve(staff); // staff holds all the data 
    } else { 
     // data is not available yet. fetch it from server 

     $http.get('staff.json') 
     .success(function(data) { 
      // once data is available resolve 
      staff = data; 
      deferred.resolve(data); 
     }) 
     .error(function (error) { 
      deferred.reject(error); 
     }); 
    } 

    return deferred.promise; 
}; 

В контроллере.

staffFactory.allStaff().then(function (staff) { 
    $scope.staff = staff; 
    console.log($scope.staff); 
    $scope.CalcPay = staffFactory.CalcPay(); 
    $scope.keyPress = function(keyCode) { 
     $scope.CalcPay = staffFactory.CalcPay(); 
    }; 
}); 

оформление покупок plunkr

+0

Спасибо, не только за ответ, но и за замечательные комментарии в коде. Это будет хорошим рабочим примером для других при работе с обещаниями. – ak85

1

Это, как я это сделал:

$scope.documents = []; 

$http.post('get_xml.php') 
    .then(function (result) { 
     $scope.documents = result.data; 
     console.log(result.data); 
    }); 

Насколько я знаю, .then асинхронная функция, которая будет обновлять массив, как только она станет доступной.

Так что в вашем случае, это должно быть:

app.factory('staffFactory', function ($http) { 

    var staff = []; 
    var test = $http.get('staff.json').then(function(result) { 
     staff = result.data; 
     console.log(staff); 
    }); 

    /* Rest of your code... */ 
}); 
+0

Спасибо. Все, что я читаю, говорит о том, чтобы оставить всю бизнес-логику вне контроллеров, я ищу рабочее решение на заводе. – ak85

Смежные вопросы