2013-09-22 25 views
5

我正在編寫一個小型的Angular Web應用程序,並且在加載數據時遇到了問題。我使用Firebase作爲數據源,並發現AngularFire項目聽起來不錯。但是,我無法控制數據的顯示方式。angularfireCollection:知道數據何時被完全加載

起初,我試圖做使用常規的隱含同步:

angularFire(ref, $scope, 'items'); 

它工作得很好,當我用在我看來,模型$項目中顯示的所有數據。但是,如果數據是從Firebase數據源到達的,則不會以視圖支持的方式進行格式設置,因此我需要在顯示數據之前對數據進行一些其他結構更改。問題是,我不知道數據何時被完全加載。我嘗試將$ watch分配給$ items,但它被稱爲過早。

所以,我提出並試圖用替代angularfireCollection:

$scope.items = angularFireCollection(new Firebase(url), optionalCallbackOnInitialLoad); 

的文檔不是很清楚什麼是「optionalCallbackOnInitialLoad」的確,當它被調用,但在嘗試訪問的第一個項目在$ items集合中會拋出一個錯誤(「Uncaught TypeError:無法讀取未定義的屬性'0')。

我嘗試添加一個按鈕,在按鈕的點擊處理我登錄的第一個項目在$項目的內容,並工作

console.log($scope.items[0]); 

它就在那裏!我Firebase中的第一個對象沒有任何錯誤地顯示出來......唯一的問題是我不得不點擊一個按鈕才能到達那裏。

因此,沒有人知道我可以知道當所有的數據已被加載並然後它分配到$ scope變量顯示在我的看法?還是有另一種方式?

我的控制器:

app.controller('MyController', ['$scope', 'angularFireCollection', 
    function MyController($scope, angularFireCollection) { 
    $scope.start = function() 
    { 
     var ref = new Firebase('https://url.firebaseio.com/days'); 
     console.log("start"); 

     console.log("before load?"); 

     $scope.items = angularFireCollection(ref, function() 
     { 
      console.log("loaded?"); 
      console.log($scope.items[0]); //undefined 
     }); 

     console.log("start() out");  
    }; 

    $scope.start(); 

    //wait for changes 
    $scope.$watch('items', function() { 
     console.log("items watch"); 
     console.log($scope.items[0]); //undefined 
    }); 

    $scope.testData = function() 
    { 
     console.log($scope.items[0].properties); //not undefined 
    }; 
    } 
]); 

我的觀點:

<button ng-click="testData()">Is the data loaded yet?</button> 

提前感謝!

+0

試試這個:angularFireCollection(參考,功能(數據) {$ = scope.items數據; 的console.log($範圍。 items [0]); }); –

回答

2

So, does anyone know how I can know when all the data has been loaded and then assign it to a $scope variable to be displayed in my view? Or is there another way?

請記住,所有Firebase調用都是異步的。您的許多問題正在發生,因爲您正嘗試訪問尚不存在的元素。按鈕點擊爲您工作的原因是因爲您在成功加載後單擊了按鈕(並訪問了這些元素)。

optionalCallbackOnInitialLoad的情況下,這是在完成angularFireCollection的初始加載後將執行的功能。顧名思義,它是可選的,這意味着如果你不想提供回調函數。

您可以使用它並指定要在加載後執行的函數,也可以使用$q承諾或您喜歡的其他承諾庫。我自己偏愛kriskowal's Q。我建議讀一下異步JavaScript,以便更深入地瞭解其中的一些問題。

警惕,這:

$scope.items = angularFireCollection(ref, function() 
     { 
      console.log("loaded?"); 
      console.log($scope.items[0]); //undefined 
     }); 

不正確地指定一個回調函數,但$scope.items沒有得到分配,直到後你跑的回調。所以它仍然不存在。

如果你只是想看看當$scope.items已經加載,你可以嘗試這樣的事:

$scope.$watch('items', function (items) { 
    console.log(items) 
}); 
+0

嗨,謝謝!回調確實有一個「結果」,但它不包含我的數據,所以我不知道它是什麼。你介意分享一個簡單的例子來說明如何在這裏實現$ q的承諾嗎?我無法理解如何在這種情況下使用它。 – iafiawik

+0

@iafiawik如果你只是爲了調試目的而做這個,你可以使用'$ scope。$ watch',我已經在上面的一個快速示例中展示了它。 –

1

在我的項目,我需要知道太多當數據被加載。我用下面的方法(隱式綁定):

$scope.auctionsDiscoveryPromise = angularFire(firebaseReference.getInstance() + "/auctionlist", $scope, 'auctionlist', []); 

$scope.auctionsDiscoveryPromise.then(function() { 
    console.log("AuctionsDiscoverController auctionsDiscoveryPromise resolved"); 
    $timeout(function() { 
     $scope.$broadcast("AUCTION_INIT"); 
    }, 500); 

}, function() { 
    console.error("AuctionsDiscoverController auctionsDiscoveryPromise rejected"); 
}); 

當$ scope.auctionsDiscoveryPromise承諾已經解決了我的廣播這是在我的指令被監聽的事件AUCTION_INIT。爲了防止某些服務或指令尚未初始化,我使用了短暫超時。

0

我用這是否會幫助任何人:

function getAll(items) { 

    var deferred = $q.defer(); 
    var dataRef = new Firebase(baseUrl + items); 
    var returnData = angularFireCollection(dataRef, function(data){ 
      deferred.resolve(data.val()); 
    }); 
    return deferred.promise; 

} 
相關問題