Kyle Shin Kyle Shin - 7 months ago 49
Javascript Question

Angular/Node/Mongoose - Rendering Post, Comment, Replies

I am creating an Application where people can ask questions. Answer- and reply to answers. I can render Posts and answers no problem, but having trouble getting replies to answers.Can someone please give me tips on the best approach to do this?



html page

<div class="container-fluid" id='post_container' ng-repeat='post in vm.posts' style='border: solid'>
<div class="row">
<div class = 'container'>
<div class='single_post'>
<h3>Topic: {{post.topic}}</h3>
<h5>Posted By: {{post.owner}} </h5>
<p>Description: {{post.description}}</p>
<form class="form-horizontal">
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">Answer</label>
<div class="col-sm-10">
<textarea class="form-control" rows="3" ng-model='vm.newAnswer[$index]'></textarea>
<button class='btn btn-primary' ng-click = 'vm.Answer(post._id, $index)' style='float:right'>Submit</button>
</div>
</form>
</div>
<em>Answers</em>
<!-- Make API Call to get answers into the container change varialbe -->
<div class='answer_container' ng-repeat = 'answer in post.answers track by $index'>
<h5><strong>{{answer._owner}}</strong>: <em> {{answer.answer}} ID {{answer._id}}</em></h5>
<div class='replies' style='margin-left: 20px'>
-find a way to get comments here
<input class='Reply' ng-model='vm.newComment'>
<input type='submit' ng-click = 'vm.Reply(answer._id)'>
</div>





angular controller

function getPosts() {
PostsFactory.getPosts()
.then(function(data) {
console.log(data)
console.log('getting POSTS')
vm.posts = data
console.log(map(vm.posts, getAnswers));
})
.catch(function(){
console.log('in the single psot controller and could not get posts')
}


Factory

function getPosts() {
var deferred = $q.defer()
$http.get('/getAnswers')
.success(function(data) {
deferred.resolve(data)
})
.error(function() {
console.log('could not get posts')
})
return deferred.promise
}


Models/Routes/Controller

var Post = new mongoose.Schema({
category: String,
topic: String,
description: String,
points: Number,
owner: String,
answers: [{type: ObjectId, ref: 'Answer'}],
date_created: Date


});

Answer

var Answer = new mongoose.Schema({
answer: String,
_post: {type: ObjectId, ref:'Post'},
_owner: String,
points: Number,
comments: [{type: ObjectId, ref: 'Comment'}],
date_created: Date


})

Comments

var Comment = new mongoose.Schema({
comment: String,
_answer: {type: ObjectId, ref: 'Answer'},
_owner: String,
points: Number,
date_created: Date


})

Controller

posts.show = function(req, res) {
Post.find()
.populate('answers')
.exec(function(err, result) {
if(err) {
console.log('error finding post')
} else {
res.json(result)
}
})


}

Answer

Mongoose supports "multi-level" population, but you need to supply that information to .populate():

posts.show = function(req,res) {
  Post.find()
    .populate({
      "path": "answers",
      "populate": {
        "path": "comments",
        "model": "Comment"  
      }
    })
    .exec(function(err,result) {
        if (err) {
           console.log(err);
        } else {
           res.json(result)
        }
    });
}

So the most that happens with a "single path" is that particular "path" is populated. But by "nesting" the "populate" arguments, then further calls are made for the other referenced items named.