0

I have been stuck for the last 3 days trying to push a new comment object into my array of comments using yo generated crud module.

Here is the server.model for my comments schema, which I am using as a subdocument:

var CommentsSchema = new Schema({

comment: {
    type: String,
    default: ''
},
user: {
    type: Schema.ObjectId,
    ref: 'User'
},
created: {
    type: Date,
    default: Date.now
}
});
mongoose.model('Comments', CommentsSchema);

This is the task schema, where I include the comments schema :

var TaskSchema = new Schema({
name: {
    type: String,
    default: '',
    required: 'Please fill Task name',
    trim: true
},
created: {
    type: Date,
    default: Date.now
},
user: {
    type: Schema.ObjectId,
    ref: 'User'
},
//comments : [{
  //  text: { type: String },
//    created: { type: Date, default: Date.now },
  //  user: { type: Schema.ObjectId, ref: 'User' }
//}]
comments: [CommentsSchema]
});
mongoose.model('Task', TaskSchema);

I can manually insert comments into a task using mongodb shell, like so:

db.tasks.update({"_id" : ObjectId("5711856735e9cb1938845048")},{ $addToSet: { comments: { "comment" : "i am also a comment"  }  } } )

however I am struggling to set up the correct function to insert into the task on my client side using a function in js/angularjs.

I have set up a form to add a new comment with:

<form name="vm.form.taskForm" class="form-horizontal" ng-submit="vm.newCo(vm.form.taskForm.$valid)" novalidate>    
<input type="text" ng-model="vm.task.comments.comment" name="comments" id="comments" placeholder="ask a question about this task">
<button type="submit">Add a comment</button>
</form>

I have updated my app.routes like so:

app.route('/api/tasks/:taskId').all(tasksPolicy.isAllowed)
.get(tasks.read)
.put(tasks.update)
.delete(tasks.delete)
.put(tasks.newCo); // this is the new function I am trying to add

and tried to set up the functionality in my server.controller

exports.newCo = function(req, res) {
var task = req.task;
var task_id = req.task._id;
Task.findByIdAndUpdate(
task_id,
{ $push : { comments: req.task.comments }},
{ safe: true, upsert: true},
    function(err) {
        if(err) {
            console.log(err, Task);
        }
        return res.json(Task);
    }
)
}

I don't quite understand how I communicate my client.controller with my server.controller to execute the function to update my task and push the comment into the array.

My latest attempt on client.controller was:

function newCo(isValid) {
        if (!isValid) {
            $scope.$broadcast('show-errors-check-validity', 'vm.form.taskForm');
                return false;
        }
        if (vm.task._id) {
                vm.task.$newCo(successCallback, errorCallback);
            } else {
                vm.task.$save(successCallback, errorCallback);
            }

        function successCallback(res) {
                $state.go('tasks.view', {
                    taskId: res._id
                });
            }

            function errorCallback(res) {
                vm.error = res.data.message;
            }
    }

If anyone could please point me in the right direction I would be so, so grateful! Thank you all in advance!

for example, this is how the remove() is working

client.controller

// Remove existing Task
    function remove() {
            if (confirm('Are you sure you want to delete?')) {
                vm.task.$remove($state.go('tasks.list'));
            }
        }

server.controller

exports.delete = function(req, res) {
    var task = req.task;
    task.remove(function(err) {
        if (err) {
            return res.status(400).send({
                message: errorHandler.getErrorMessage(err)
            });
        } else {
            res.jsonp(task);
        }
    });
};

server.routes.js

  app.route('/api/tasks/:taskId').all(tasksPolicy.isAllowed)
    .get(tasks.read)
    .put(tasks.update)
    **.delete(tasks.delete)**

and finally, html view:

<a class="btn btn-primary" data-ng-click="vm.remove()">
  <i class="glyphicon glyphicon-trash"></i>
</a>
amyloula
  • 1,556
  • 2
  • 17
  • 26

1 Answers1

1

You can follow this process:

In html:

You don't need to pass vm.form.taskForm.$valid in newCo function can check from form. submit button can keep disable if form invalid ng-disabled="vm.form.taskForm.$invalid". Also can use ng-model="vm.task.newComment" instead of ng-model="vm.task.comments.comment" because of you want to add new comment so no need to use comments.comment. so can use html like:

<form name="vm.form.taskForm" class="form-horizontal" ng-submit="vm.newCo()" novalidate>
    <input type="text" ng-model="vm.task.newComment" name="comments" id="comments" placeholder="ask a question about this task">
    <button type="submit" ng-disabled="vm.form.taskForm.$invalid">Add a comment</button>
</form>

and I guess you used controller as like ng-controller="yourCtrl as vm" or in route provider used like controllerAs: 'vm'

In your controller:

var vm = this;
vm.task = task //predefined
vm.newCo = function() {
  // used $http.put('/api/tasks/21' according to your server side route
  $http.put('/api/tasks/21', {
    comment: vm.task.newComment;
  }).then(successCallback, errorCallback); //say 21 is taskId

  function successCallback(res) {
    $state.go('tasks.view', {
      taskId: res.data._id
    });
  }

  function errorCallback(res) {
    vm.error = res.data.message;
  }
};

Server side controller:

exports.newCo = function(req, res) {
  Task.findOneAndUpdate({_id: req.params.taskId}, 
    {
      "$push": {
        comments: req.body.comment
      }
    }, {
      new: true //to return updated document
    })
    .exec(function(error, task) {
      if (error) {
        return res.status(400).send({message: 'Failed to add comment due to invalid params!'});
      }
      return res.status(200).send(task);
    });
};

and in your schema should use Schema.Types.ObjectId instead of Schema.ObjectId

user: {
    type: Schema.Types.ObjectId,
    ref: 'User'
}
Shaishab Roy
  • 16,335
  • 7
  • 50
  • 68
  • hey @shaishab roy thanks so much for your input. I have tried your suggestions however jshint is throwing some errors on running grunt. I was wondering if you have a suggestion for client side without $http.put('/api/tasks/21', { in the function. for example, the remove function I have added to my edit – amyloula Apr 17 '16 at 17:12
  • ok, can you show your full controller and ui in plunker to better understand @loulala – Shaishab Roy Apr 17 '16 at 18:01
  • I made a slight tweak to client controller and am now succesfully pushing into the array. thanks very much @shaishab – amyloula Apr 17 '16 at 21:59
  • I tried to replicate the function for another form, however every time I press submit it pushes a null value to my comments array, rather than my new array. I have renamed the function and changed the variables for the client side controller and the req.body for the server side, do you have any idea why this would be happening? – amyloula Apr 21 '16 at 16:30
  • can you show your `$http.put(..` method and how received in server side? @loulala – Shaishab Roy Apr 21 '16 at 18:34
  • thanks so much for getting back to me. in the end I had to use a put request to get the function to work. here is copies of the current code: http://stackoverflow.com/questions/36777769/angularjs-can-i-have-two-post-requests-resolving-to-same-api-endpoint – amyloula Apr 21 '16 at 18:37
  • @ShaishabRoy http://stackoverflow.com/questions/43113867/how-to-store-table-with-particular-column-should-stored-in-array-and-retrieve-it – jose Mar 30 '17 at 09:50