2013-09-22 28 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; 

} 
相关问题