I am building a social media web app and trying to add posts and comments dynamically via ajax. The posts are being added successfully but comments are not being added because the success event isn't firing. Even error event is not being fired. But the AJAX call is being completed (I checked it by adding console.log statements before call, in the success event and error event and after the call).
Here is the code that I wrote:-
This is the code for initiating AJAX call using classes (The problem is in createComment method, rest of the code is for reference to other methods used in createComment):-
class PostComments{
// constructor is used to initialize the instance of the class whenever a new instance is created
constructor(postId){
this.postId = postId;
this.postContainer = $(`#post-${postId}`);
this.newCommentForm = $(`#post-${postId}-comments-form`);
this.createComment(postId);
let self = this;
// call for all the existing comments
$(' .delete-comment-button', this.postContainer).each(function(){
self.deleteComment($(this));
});
}
createComment(postId){
let pSelf = this;
this.newCommentForm.submit(function(e){
e.preventDefault();
let self = this;
$.ajax({
method: 'post',
url: '/comments/create',
data: $(self).serialize(),
success: function(data, textStatus, xhr){
console.log(data);
let newComment = pSelf.newCommentDom(data.data.comment, data.data.comment_user);
$(`#post-comments-${postId}`).prepend(newComment);
pSelf.deleteComment($(' .delete-comment-button', newComment));
new Noty({
theme: 'nest',
text: "Comment published!",
type: 'success',
layout: 'topRight',
timeout: 1500
}).show();
},
error: function(error){
console.log(error.responseText);
}
});
});
}
newCommentDom(comment, comment_user){
// I've added a class 'delete-comment-button' to the delete comment link and also id to the comment's li
return $(`<li id="comment-${ comment._id }">
<p>
<small>
<a href="/comments/destroy/${comment._id}">X</a>
</small>
${comment.content}
<br>
<small>
${comment_user}
</small>
</p>
</li>`);
}
deleteComment(deleteLink){
$(deleteLink).click(function(e){
e.preventDefault();
$.ajax({
method: 'get',
url: $(deleteLink).prop('href'),
success: function(data){
$(`#comment-${data.data.comment_id}`).remove();
new Noty({
theme: 'nest',
text: "Comment Deleted",
type: 'success',
layout: 'topRight',
timeout: 1500
}).show();
},
error: function(error){
console.log(error.responseText);
}
});
});
}
}
This is the code of my controller action for creating comments:-
module.exports.create = async function(req, res){
try{
let post = await Post.findById(req.body.post);
if (post){
let comment = await Comment.create({
content: req.body.content,
post: req.body.post,
user: req.user._id
});
post.comments.push(comment);
post.save();
let comment_user = await Comment.find(comment._id).populate('user');
if (req.xhr){
return res.status(200).json({
data: {
comment: comment,
comment_user: comment_user.user.name
},
message: "Comment created!"
});
}
req.flash('success', 'Comment published!');
res.redirect('/');
}
}catch(err){
req.flash('error', err);
return;
}
}
This is my posts and comments view partials:-
posts.ejs
<li id="post-<%= post._id %>">
<p>
<% if (locals.user && locals.user.id == post.user.id){ %>
<small>
<a href="/posts/destroy/<%= post.id %>">X</a>
</small>
<% } %>
<%= post.content %>
<br>
<small>
-<%= post.user.name %>
</small>
</p>
<div >
<% if (locals.user){ %>
<!-- let's give an id to the new comment form, we'll also need to make the same changes in home_posts.js where we're adding a post to the page -->
<form id="post-<%= post._id %>-comments-form" action="/comments/create" method="POST">
<input type="text" name="content" placeholder="Add Comment..." required>
<input type="hidden" name="post" value="<%= post._id %>" >
<button type="submit">Add</button>
</form>
<% } %>
<div >
<ul id="post-comments-<%= post._id %>">
<% for (comment of post.comments){%>
<%- include('_comment') -%>
<%} %>
</ul>
</div>
</div>
</li>
comments.ejs
<li id="comment-<%= comment._id %>">
<p>
<% if(locals.user && (locals.user.id == comment.user.id || locals.user.id == post.user.id)){ %>
<small>
<a href="/comments/destroy/<%= comment.id %>">X</a>
</small>
<% } %>
<%= comment.content %>
<br>
<small>
<%= comment.user.name %>
</small>
</p>
</li>
Edit:- I inspected the request in developer tools and found out that it remains pending forever
CodePudding user response:
The problem has been solved. In controller action, I had written Comment.find(comment._id)
instead of Comment.findById(comment._id)
which is why due to await keyword it was pending forever and the success callback wasn't firing.