在angularfire 1.0.0中通过唯一的firebase id获取项目

时间:2015-03-18 17:57:47

标签: arrays angularjs key firebase angularfire

使用angularfire 1.0.0从我的firebase中获取一个唯一项目时遇到问题。为了澄清,我希望我的应用程序在给定唯一的firebase id的情况下获取帖子,例如“-JkZwz-tyYoRLoRqlI_I”。它在应用程序中导航时有效,例如单击指向特定帖子的链接,但不刷新。我的猜测是它与同步有关。现在它可以在获取所有帖子并在ng-repeat中使用它时起作用。这是导航到页面时为什么它适用于一个项目的线索。这应该不是很难,因为这应该是一个非常标准的操作,但我不能让它工作。我到处搜索,但实际上没有这方面的指南。在API中,它们引用$getRecord(key)

  

返回给定键的数组记录。如果关键不是   找到后,返回null。这个方法利用$ indexFor(key)来查找   适当的记录。

但这不符合预期。或者我错过了什么?

它适用于ng-repeat,如下所示:

<div ng-repeat="postt in posts">
   <div>
      <h1>{{postt.title}}</h1>
      <div>{{postt.timestamp}}</div>
      <div>{{postt.content}}</div>
   </div>
</div>

但不适合这样的独特物品:

<div>
   <h1>{{post.title}}</h1>
   <div>{{post.timestamp}}</div>
   <div>{{post.content}}</div>
</div>

这是服务:

'use strict';

angular.module('app.module.blog.post')

.factory("PostService", ["$firebaseArray", "FIREBASE_URL", function($firebaseArray, FIREBASE_URL) {

    var ref = new Firebase(FIREBASE_URL + "posts");
    var posts = $firebaseArray(ref);

    return {
        all: posts, // ng-repeat on this works fine

        last: function(nr) {
            var query = ref.orderByChild("timestamp").limitToLast(nr);
            return $firebaseArray(query); // ng-repeat on this work fine to
        },
        create: function (post) {
            return posts.$add(post);
        },
        get: function (postId) {
            console.log(postId); // This is -JkZwz-tyYoRLoRqlI_I
            var post = posts.$getRecord(postId);
            console.log(post); // This print null
            return post;
        },
        delete: function (post) {
            return posts.$remove(post);
        }
    };
}]);

正如评论在get函数中所说的那样,postId就在那里,并且也设置了帖子,但帖子是空的。

这是控制器

'use strict';

angular.module('app.module.blog.post', [])

.controller('PostCtrl', ['$scope', '$routeParams', 'PostService', function($scope, $routeParams, PostService) {

    // This returns e.g. postId "-JkZwz-tyYoRLoRqlI_I"
    console.log($routeParams.postId);

    $scope.post = PostService.get($routeParams.postId);    
    $scope.posts = PostService.all; // Illustrates the example not actually in this controller otherwise

}]);

这是firebase数据库中的内容的一个示例

<myfirebase>
 posts
 -JkUnVsGnCqbAxbMailo
 comments
 content: ...
 timestamp: ...
 title: ...
 -JkZwz-tyYoRLoRqlI_I
 comments
 content: ...
 timestamp: ...
 title: ...
 -JkhaEf9tQy06cOF03Ts
 content: ...
 timestamp: ...
 title: ...

我发现这个问题非常奇怪,因为它应该非常标准。我显然错过了一些东西,但无法解决这个问题。非常感谢任何帮助!

提前致谢!

2 个答案:

答案 0 :(得分:5)

我知道$getRecord()函数的文档有点误导。您实际从$firebaseArray获得的是数组的promise。这意味着您的posts变量将在未来的某个时间点包含您的帖子。话虽如此,$getRecord函数似乎只有在解析了promise时才有效,即从Firebase下载数组时。要确保在调用$getRecord函数时解决了承诺,您可以在承诺上使用$loaded()

var posts = $firebaseArray(ref);
posts.$loaded().then(function(x) {
    var post = x.$getRecord(postId);
    console.log(post);
}).catch(function(error) {
    console.log("Error:", error);
});

如果你想知道为什么它适用于ng-repeat,那是因为Angular知道posts变量是一个promise并等待它在呈现值之前被解析。

答案 1 :(得分:2)

这是由于承诺而发生的。

  • 就像加藤一样,让 - 菲利普说,$firebaseArray因为需要下载而无法立即使用。
  • 请参阅.$loaded()文档:

      

    .$loaded()“返回从Firebase下载初始数组数据时解析的承诺。承诺解析为$ firebaseArray本身。”

  •   
  这回答了你的问题,我只是想表明另一种方式:

  • 这是扩展AngularFire服务的一个很好的用例。
    • 正如AngularFire API Documentation所说:

        

      “有几种强大的技术可以转换$firebaseArray$firebaseObject下载和保存的数据。这些技术只能由熟悉代码的高级Angular用户尝试。”

    •   
  •   
  • 把所有这些放在一起,你完成了你想做的事情:   
  •   

     

实施例

  • 这是一个有效的JSFIDDLE example,它与我的一个公共Firebase实例绑定在一起。
  • 请务必注意,您应在".indexOn":"timestamp"的规则中添加/posts

工厂

app.factory('PostsArray', function (FBURL, PostsArrayFactory) {
    return function (limitToLast) {
        if (!limitToLast) {
            console.error("Need limitToLast");
            return null;
        }
        var postsRef = new Firebase(FBURL + '/posts').orderByChild('timestamp').limitToLast(limitToLast);
        return new PostsArrayFactory(postsRef);
    }
});


app.factory('PostsArrayFactory', function ($q, $firebaseArray) {
    return $firebaseArray.$extend({
        getPost: function (postKey) {
            var deferred = $q.defer();
            var post = this.$getRecord(postKey);
            if (post) {
                console.log("Got post", post);
                deferred.resolve(post);
            } else {
                deferred.reject("Post with key:" + postKey + " not found.");
            }
            return deferred.promise;
        },
        createPost: function (post) {
            var deferred = $q.defer();
            post.timestamp = Firebase.ServerValue.TIMESTAMP;
            this.$add(post).then(function (ref) {
                var id = ref.key();
                console.log("added post with id", id, "post:", post);
                deferred.resolve(ref);
            }).
            catch (function (error) {
                deferred.reject(error);
            });
            return deferred.promise;
        }
    });
});

控制器

app.controller("SampleController", function ($scope, PostsArray) {

    var posts = new PostsArray(5);
    $scope.posts = posts;

    $scope.newPost = {};
    $scope.createNewPost = function () {
        posts.createPost($scope.newPost);
    }

    $scope.postId = '';
    $scope.getPost = function () {
        posts.getPost($scope.postId).then(function (post) {
            $scope.gotPost = post;
        }).
        catch (function (error) {
            $scope.gotPost = error;
        });
    }
});