2013-11-29 47 views
1

基本上,我的應用程序的核心圍繞通過$ http請求從服務器檢索的一組數據。一旦數據可用於客戶端(作爲一個對象數組),我需要它爲多個視圖,並希望維護它們之間的狀態,例如,如果它已被過濾,我只想過濾的數據可用其他意見。Angularjs服務來管理跨多個控制器的數據集

目前我有一個基本的服務檢索數據,然後管理應用程序範圍控制器中的數據(數組)的狀態(見下文)。這工作正常,但它開始變得一團糟,因爲我試圖維持陣列長度,過濾狀態,每個視圖控制器上的可見/隱藏對象,因爲我必須在應用程序範圍的控制器中保留currentVenue等的軌跡。注意:我在每個視圖中使用ng-repeat來顯示和過濾數據(另一個原因是我希望在中心點進行過濾)。

顯然這不是最優的。我假設我應該使用服務來維護場地對象數組,因此它將包含當前場地,當前頁面,負責過濾數組等,並將其注入到每個控制器中。我的問題是,我如何設置一個服務來實現這個功能(包括從服務器啓動時加載數據;這將是一個很好的開始tbh),以便我可以實現這一點,然後將結果綁定到範圍。即:在每個視圖控制器中的某個東西$scope.venues = venues.getVenues$scope.current = venues.currentVenue

services.factory('venues', function ($http, $q) { 
    var getVenues = function() { 
     var delay = $q.defer(); 

     $http.get('/api/venues', { 
      cache: true 
     }).success(function (venues) { 
      delay.resolve(venues); 
     }); 

     return delay.promise; 
    } 

    return { 
     getVenues: getVenues 
    } 
}); 

controllers.controller('AppCtrl', function (venues, $scope) { 
    $scope.venuesPerPage = 3; 

    venues.getVenues().then(function (venues) { 
     $scope.venues = venues; 
     $scope.numVenues = $scope.venues.length; 
     $scope.currentPage = 0; 
     $scope.currentVenue = 0; 
     $scope.numPages = Math.ceil($scope.numVenues/$scope.venuesPerPage) - 1; 
    } 
}); 

對不起,很長的措辭,不知道如何確切地指定它。提前致謝。

回答

2

我很快就把它們放在一起作爲出發點。您可以以任何您想要的方式重組工廠。總的想法是,範圍內的所有數據現在都已移至工廠服務中的對象。

與僅使用響應數組解決$http相反,使用包含來自服務器的數組的更大的對象解決此問題。由於所有的數據現在是在一個對象可以從任何控制器

services.factory('venues', function ($http, $q) { 
    var getVenues = function(callback) { 
     var delay = $q.defer(); 

     $http.get('/api/venues', { 
      cache: true 
     }).then(function (response) { 
       /* update data object*/ 
       venueData.venues=response.data; 
       venueData.processVenueData(); 
       /* resolve with data object*/ 
       delay.resolve(venueData); 
     }).then(callback); 

     return delay.promise; 
    } 

    var processVenueData=function(){ 
     /* do some data manipulation here*/ 
     venueData.updateNumPages(); 
    } 


    var venueData={ 
     venuesPerPage : 3, 
     numVenues:null, 
     currentVenue:0, 
     numPages:null, 
     venues:[], 
     updateNumPages:function(){ 
      venueData.numPages = Math.ceil(venueData.numVenues/venueData.venuesPerPage) - 1; 
     }, 
     /* create some common methods used by all controllers*/ 
     addVenue: function(newVenue){ 
      venueData.venues.push(newVenue) 
     } 
    } 

    return { 
     getVenues: getVenues 
    } 
}); 

controllers.controller('AppCtrl', function (venues, $scope) { 

    venues.getVenues(function (venueData) { 
     /* now have much bigger object instead of multiple variables in each controller*/ 
     $scope.venueData=venueData; 
    }) 
}); 

現在,在標記基準venueData.venuesvenueData.numPages

被更新通過跨控制器共享方法,你現在可以簡單地結合形式的對象與ng-model的到一個具有ng-click="venueData.addVenue(formModel)"(或使用ng-submit)的按鈕,並且您可以從任何控制器/指令添加新場地而無需向控制器添加一點代碼

+0

感謝您的詳細答覆@charlietfl。我已經整合了你的意見,這是一個很好的開始,但有一個問題。如果我使用'getVenues()'的承諾方法,我會在每個視圖控制器中調用'getVenues()'嗎? (試圖再次避免應用程序範圍的appCtrl方法)還是應該只調用一次實例化,然後在每個控制器中調用一個方法來僅返回對象引用?或者,如果剛剛返回一個對象,如m59所示,我如何確保'場地'數組在第一個對象請求上填充並在返回對象之前實例化? – adamK

+0

因爲我不確定應用程序是如何工作的,所以假設只會在所有控制器中調用相同的東西。由於緩存設置爲真,只會向服務器發出一次請求。您可以重新設計,因此只有基於另一個已經進行初始調用的控制器纔會返回m5p樣式的數據。使用我的方法,無論哪個控制器首先行動 – charlietfl

+0

理解,也許一個簡單的初始化標誌就足以避免重新處理數據。謝謝您的幫助! – adamK

3

策略是利用對象引用。如果將共享數據移動到某個對象,然後將該對象設置爲$scope,則$ scope上的任何更改都將直接更改服務對象,因爲它們是相同的東西($scope指的是服務)。

Here's a live sample demonstrating this technique (click).

<div ng-controller="controller-one"> 
    <h3>Controller One</h3> 
    <input type="text" ng-model="serv.foo"> 
    <input type="text" ng-model="serv.bar"> 
    </div> 
    <div ng-controller="controller-two"> 
    <h3>Controller Two</h3> 
    <input type="text" ng-model="serv.foo"> 
    <input type="text" ng-model="serv.bar"> 
    </div> 

JS:

var app = angular.module('myApp', []); 

app.factory('myService', function() { 
    var myService = { 
    foo: 'abc', 
    bar: '123' 
    }; 
    return myService; 
}); 

app.controller('controller-one', function($scope, myService) { 
    $scope.serv = myService; 
}); 

app.controller('controller-two', function($scope, myService) { 
    $scope.serv = myService; 
}); 
相關問題