3

I created a Reddit clone using AngularJS and Firebase. I am working on allowing posting comments to comments (a comment thread). Firebase does not like using nested arrays, it prefers a flatten structure. I found this example of using Firebase to create nested comments, but it uses jQuery and I am really unclear how to 'translate'.

How would I go about creating "nested" (threaded) comments without actually using nested arrays?

This is my comment controller (called PostViewCtrl):

'use strict';

app.controller('PostViewCtrl', function ($scope, $routeParams, Post, Auth) {

  $scope.user = Auth.user;
  $scope.signedIn = Auth.signedIn;
  $scope.post = Post.get($routeParams.postId);

  $scope.comments = Post.comments($routeParams.postId);

  $scope.addComment = function () {
    if(!$scope.commentText || $scope.commentText === '') {
      return;
    }
    var comment = {
      text: $scope.commentText,
      creator: $scope.user.profile.username,
      creatorUID: $scope.user.uid
    };

    $scope.comments.$add(comment);
    $scope.commentText = '';
  };

  $scope.deleteComment = function (comment) {
    $scope.comments.$remove(comment);
  };

});

And this is my Post service (to communicate with Firebase):

'use strict';

app.factory('Post', function ($firebase, FIREBASE_URL) {
  var ref = new Firebase(FIREBASE_URL);
  var posts = $firebase(ref.child('posts')).$asArray();

  var Post = {
    all: posts,
    create: function (post) {
      return posts.$add(post).then(function(postRef) {
        $firebase(ref.child('user_posts').child(post.creatorUID))
                          .$push(postRef.name());
        return postRef;
      });
    },
    get: function (postId) {
      return $firebase(ref.child('posts').child(postId)).$asObject();
    },
    delete: function (post) {
      return posts.$remove(post);
    }, 
    comments: function (postId) {
      return $firebase(ref.child('comments').child(postId)).$asArray();
    }

  };

  return Post;
});

1 Answers1

3

Both the DOM and a comment thread are tree data structures. HTML is built to support trees, but it is a common problem to store them in databases. One solution to this problem is to using an adjacency list.

In this list, each resource, or in this case comment, would store a parent_id that is identical to the id of the comment it is nested under—creating a "flat" data structure.

It is important to acknowledge that Firebase uses Mongo, which is a hierarchical database, so it is possible to "nest" data; however, this is advised against by the creators, so let's stick with the "flat" approach.

Given we now have a "flat" data structure, we still need to convert it into a nested data structure so it can render nicely to the DOM. Here's an example of how to build a tree from a flat data structure in JavaScript and here's a library to the same effect.

Finally, once you have your nested comments, or a comment thread, I'd recommend following this blog post on building a nested, recursive directive in angular to render it to the DOM.

Hope this helps!

Community
  • 1
  • 1
IliasT
  • 3,973
  • 1
  • 24
  • 26