在帖子中加载评论

时间:2015-12-04 20:49:48

标签: javascript angularjs firebase angularfire

假设我的Firebase DB中有这个结构

enter image description here

编辑: 我的JSON结构如下所示:

{
  ad-comments:{
    48a047b7-28a2-4037-925c-2a809b8d4445:{
      -K4iGKXbniQZUi4r1SW7:{
         Comment:""
         Email:""
         Date:""
         Submitter:""
         ID:""
      }
      -K4hxcKuuxcwuhScPR_v:{...}    
    }
    eeb082e5-59ed-4c3b-8fcd-5af24a2bcada:{...}    
  }
  users:{
    48a047b7-28a2-4037-925c-2a809b8d4445:{
      text:""
      name:""
      email:""
      desc:""
      phone:""
    }
    444198db-1052-4d8d-a1cd-c7e613fbe7c9:{...}  
  }
}

在控制器中我检索用户(每个用户都有一个属性帖子),使用$ firebaseArray和ng-repeat在视图中显示它们,如下所示:

var ref = new Firebase ("https://url.firebaseio.com/users");
$scope.posts = $firebaseArray("ref");

现在在视图中我只是使用ng-repeat来迭代它们

<div ng-repeat="post in posts">

  <div>{{post.name}}</div>
  <div>{{post.text}}</div>

  <div>Comments:<div>
     <div><input type="text" ng-model="comment"></div>
     <div><button ng-click="addComment(post, comment)">Add</button></div>
</div>

现在,问题是如何在每个帖子位于不同节点时进行查询以请求所有评论,我按ID存储它们但仍无法弄清楚如何操作。

在我将评论存储在每个用户中之前,可以在每个帖子上显示评论,但我遇到了安全规则的问题,因为我已经指定用户只能修改自己的内容而不是其他人,并将评论留在用户内部并不允许其他人发表评论,所以我不得不改变并将评论放在不同的节点中。

2 个答案:

答案 0 :(得分:3)

您保持数据平稳,这太棒了!

您还在两个位置之间使用共享密钥,这意味着您将有90%的位置。

有多种方法可以处理这种情况,但using .$extend() in AngularFire提供了一个优雅的解决方案。

下面的代码示例使用Angular Styleguide,所以如果代码看起来不熟悉,请不要担心。

Here's the full demo on JSBin以及以下是创建它的步骤。

我们希望为每个用户加载评论。我们首先创建一个工厂,ad-comments uid

function UserCommentsArray($firebaseArray, rootRef) {
  return function UserCommentsArray(uid) {
    var userCommentsRef = rootRef.child('ad-comments').child(uid);
    return $firebaseArray(userCommentsRef);
  };
}

现在我们将使用$firebaseArray.$extend()创建自定义同步数组。

function UsersArray($firebaseArray, rootRef, userCommentsArray) {
    return $firebaseArray.$extend({
      $$added: function(snap) {
        var user = snap.val();
        user.$id = snap.key();
        user.comments = userCommentsArray(snap.key());
        return user;
    }
  });
}

每次将一个项目添加到数组中时,我们都会创建一个用户对象并添加userCommentsArray的评论。

现在在我们的控制器代码中,我们可以简单地注入usersArray并绑定到页面。

function MyCtrl($scope, rootRef, usersArray) {
  var usersRef = rootRef.child('users');
  $scope.users = usersArray(usersRef);
}

在页面上显示此数据需要更改模板:

  <div ng-controller="MyCtrl">

    <div ng-repeat="user in users">

      <div>{{user.name}}</div>

      <ul ng-repeat="comment in user.comments">
        <li>{{ comment.text }}</li>
      </ul>

      <div>Comments:</div>
      <div>
        <input type="text" ng-model="newComment">
      </div>

      <div>
        <button 
          ng-click="addComment(user, newComment)">Add
        </button>
      </div>

    </div>
  </div>

在用户下添加评论是通过找到用户然后在评论数组上调用$add()来完成的。

function MyCtrl($scope, rootRef, usersArray) {
  var usersRef = rootRef.child('users');
  $scope.users = usersArray(usersRef);
  $scope.addComment = function (user, newComment) {
    var userRecord = $scope.users.$getRecord(user.$id);
    userRecord.comments.$add({ text: newComment });
  };
}

答案 1 :(得分:1)

我不是Firebase专家,但我认为您应该考虑如何建模帖子及其评论之间的联系。 我可以想到两种方式:

  1. 发布实体将有一个额外的字段:

    列出commentIds

  2. 评论实体将保留帖子的ID

  3. 我建议采用第一种方法,因为通常我们希望所有者实体(在本例中为Post实体)保留其子项(评论)

    现在,当您检索帖子时,请确保使用评论ID检索其所有评论。