简体   繁体   English

无法在指令angularjs中从Firebase获取数据

[英]Cannot get data from firebase in directive angularjs

I'm doing a slider following the steps from this tutorial using Angular.js and Firebase API. 我正在使用Angular.js和Firebase API按照本教程中的步骤进行操作。

I have created a directive 'slider' in my directive file, here is the code: 我在指令文件中创建了指令“ slider”,下面是代码:

.directive('slider', function()
{
    return {
        restrict: 'E',
        replace: true,
        link: function(scope, elem, attrs) {
            scope.currentIndex = 0; // Initially the index is at the first slide

            scope.next = function()
            {
                scope.currentIndex < scope.challenges.length - 1 ? scope.currentIndex++ : scope.currentIndex = 0;
            };

            scope.prev = function()
            {
                scope.currentIndex > 0 ? scope.currentIndex-- : scope.currentIndex = scope.challenges.length - 1;
            };

            scope.$watch('currentIndex', function()
            {
                scope.challenges.forEach(function(challenge)
                {
                    challenge.visible = false; // make every challenge invisible
                });

                scope.challenges[scope.currentIndex].visible = true; // make the current challenge visible
            });
        },
        template: '<div></div>'
    };

I have no isolate scope, as you see, so it should take scope.challenges from parent, but it comes as undefined value instead of the data from Firebase. 如您所见,我没有隔离范围,因此它应该采用来自父级的scope.challenges,但它是未定义的值而不是Firebase的数据。

So doing forEach of undefined it throws an error: TypeError: Cannot read property 'forEach' of undefined 因此,执行未定义的forEach会引发错误: TypeError:无法读取未定义的属性'forEach'

I spent like 3 hour trying to understand scopes, a solution will be so rewarding. 我花了大约3个小时来尝试了解范围,因此解决方案将非常有益。 Thank you very much. 非常感谢你。

@rizome thank you very much for your answer, it was really useful. @rizome非常感谢您的回答,它非常有用。

Firebase API returns directly a promise, so you don't have to do so. Firebase API直接返回承诺,因此您不必这样做。

Finally I resolve it, updating 'angularfire' to v0.8 and this code: 最后,我将其解决,将“ angularfire”更新为v0.8和以下代码:

// Controller code
Challenge.findAll().$asArray().$loaded().then(function(challenges)
{
    $scope.challenges = challenges;
});

Basically what it does is wait till challenges are ready to assign. 基本上,它的工作是等到准备好分配挑战。

This article from firebase was really a good resource to solve it. firebase的这篇文章确实是解决该问题的好资源。

I don't know if I missunderstood, but: 我不知道我是否误会了,但是:

var currentIndexChangeHandler = function(newValue, oldValue) {
    scope.challenges.forEach(function(challenge) {
        //do something
    }
}
scope.$watch('currentIndex', currentIndexChangeHandler);

will provoke that " currentIndexChangeHandler " will be triggered on the very first run (see: $watch is triggered directly after init, why? ), when " scope.challenges " is still undefined. 将引发“ currentIndexChangeHandler ”将在第一次运行时被触发(请参阅: $ watch在init之后直接触发,为什么? ),而“ scope.challenges ”仍未定义。

You colud "hack" this "first run" with " if(newValue!=oldValue) ", but I think this is not the point. 您用“ if(newValue!= oldValue) ”来“破解”该“首次运行”,但是我认为这不是重点。 Other problem is that when you iterate " scope.challenges ", it is undefined, because its value should be async received. 另一个问题是,当您迭代“ scope.challenges ”时,它是未定义的,因为它的值应该是异步接收的。 It could be solved using " if(Boolean(scope.challenges)) ", but it's not the right way. 可以使用“ if(Boolean(scope.challenges)) ”解决,但这不是正确的方法。

I think the real problem is that you are working with async data. 我认为真正的问题是您正在使用异步数据。

¿What value returns Challenge.findAll()? ¿什么值返回Challenge.findAll()? ¿maybe a promise? ¿可能是一个承诺? In this way you should use: 这样,您应该使用:

Challenge.findAll().then(function(challenges){
    $scope.challenges = challenges;
}

I refactored your code with my sugestion. 我通过我的建议重构了您的代码。 Is that behaviour, what you was pretending? 那是你的假装吗?

http://jsfiddle.net/rizome/uqtaoLne/ http://jsfiddle.net/rizome/uqtaoLne/

UPDATE: 更新:

Using Firebase and $firebase (see: https://www.firebase.com/docs/web/libraries/angular/api.html#angularfire-firebase ) 使用Firebase和$ firebase(请参阅: https : //www.firebase.com/docs/web/libraries/angular/api.html#angularfire-firebase

" $firebase " AngularJS wraper has a similar behaviour than coded in the fiddle above, but you should use " $firebase " api to obtain a promises. $ firebase” AngularJS包装器的行为与上面的小提琴中编码的行为类似,但是您应使用“ $ firebase ” api获得承诺。 (this piece of code represents code inside your repo-service, and inside the controller as well) (这段代码代表您的回购服务内部以及控制器内部的代码)

var firebaseResource = $firebase(new Firebase(YOUR_DATA_URL));
var firebaseSyncArray = firebaseResource.$asArray(); //it is still empty
var loadedArrayPromise = firebaseSyncArray.$loaded(); //promise with the array when loaded
var loadedArrayPromise.then(function (challenges) {
        $scope.challenges = challenges; //now, you can set $scope.challenges
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM