I'm creating a social network site using Laravel. I have a page that load all the posts created by users the currentUser follows. I have a comment section on each post. I'm using ajax to post the comments.
Here is my code.
Here is the view of the comment-box
. It contains a section where I loop through each comment and display them. At the end is the type field so a user can post a new comment:
<div class="comment-box-container ajax-refresh">
<div class="comment-box">
@if ($type->comments)
@foreach ($type->comments as $comment)
<div class="user-comment-box">
<div class="user-comment">
<p class="comment">
<!-- starts off with users name in blue followed by their comment-->
<span class="tag-user"><a href="{{ route('profile', $comment->owner->id) }}">{{ $comment->owner->first_name }} {{ $comment->owner->last_name }}</a> </span>{{ $comment->body }}
</p>
<!-- Show when the user posted comments-->
<div class="com-details">
<div class="com-time-container">
{{ $comment->created_at->diffForHumans() }} ·
</div>
</div>
</div><!--user-comment end-->
</div><!--user-comment-box end-->
@endforeach
@endif
<!--type box-->
<div class="type-comment">
<div class="type-box">
{{ Form::open(['data-remote', 'route' => ['commentPost', $id], 'class' => 'comments_create-form']) }}
{{ Form::hidden('user_id', $currentUser->id) }}
{{ Form::hidden($idType, $id) }}
{{--{{ Form::hidden('user_id', $currentUser->id) }}--}}
{{ Form::textarea('body', null, ['class' =>'type-box d-light-solid-bg', 'placeholder' => 'Write a comment...', 'rows' => '1']) }}
{{ Form::close() }}
</div><!--type-box end-->
</div><!--type-comment-->
</div><!--comment-box end-->
The user submit the form for the comment type box by pressing the "enter/return" key. Here is the JS for that
<script>
$(document).on('keydown', '.comments_create-form', function(e) {
if (e.keyCode == 13) {
e.preventDefault();
$(this).submit();
}
});
</script>
Here is my Ajax
(function(){
$(document).on('submit', 'form[data-remote]', function(e){
e.preventDefault();
var form = $(this)
var target = form.closest('div.ajax-refresh');
var method = form.find('input[name="_method"]').val() || 'POST';
var url = form.prop('action');
$.ajax({
type: method,
url: url,
data: form.serialize(),
success: function(data) {
var tmp = $('<div>');
tmp.html(data);
target.html( tmp.find('.ajax-refresh').html() );
target.find('.type-box').html( tmp.find('.type-box').html() );
tmp.destroy();
}
});
});
})();
When I post a comment on the first post it all works fine. However, when I post a comment on the second, third, fourth etc it only displays the comments from the first post. I have to manually refresh the page, then the correct comments will display.
I'll try to illustrate this problem with images.
Starting fresh, I can easily submit 2 comments on POST 1 http://s27.postimg.org/6ej76hunn/comment1.jpg
When I scroll down to Post 2, I see it already has a comment, I will submit a new comment http://s23.postimg.org/x65ui2ryz/comment_2.jpg
HERE'S THE PROBLEM: When I submit the comment on POST 2, the comments that were in POST 2 disappears, and are replaced by the comments from POST 1. http://s30.postimg.org/ugl08oz01/comment_3.jpg
The back end still worked, because when I reload the page everything is the way it should be http://s9.postimg.org/w51fgyzen/comment_4.jpg
When I check the console Ajax is returning the entire page.
I'm completely stuck. Does anyone know why this is happening and how to fix it?
EDIT
Here is my controller that is loading the page with the posts:
public function index()
{
// load posts into the view.
$posts = $this->postRepository->getFeedForUser(Auth::user());
return View::make('newsfeed', compact('posts'));
}
The getFeedForUser()
is this:
public function getFeedForUser(User $user)
{
// get a list of all the ids the user follows
$userIds = $user->followedUsers()->lists('followed_id');
// add in the current users posts as well
$userIds[] = $user->id;
// Resource is the posts
return Resource::with('messages', 'media', 'user', 'videos', 'comments', 'locations')->whereIn('user_id', $userIds)->latest()->get();
}
That Resource
model has the relationship for the comments. It looks like this:
class Resource extends Eloquent {
public function comments()
{
return $this->hasMany('Duuer\Comments\Comment');
}
}
The route for saving a comment to the DB looks like this:
Route::post('post/{id}/comment', ['as' => 'commentPost', 'uses' => 'CommentsController@postComment']);
The CommentsController
looks like this:
class CommentsController extends \BaseController {
use CommanderTrait;
/**
* Leave a new comment
* @return Response
*/
public function postComment()
{
extract(Input::only('user_id', 'resource_id', 'body'));
$this->execute(new PostCommentCommand($user_id, $resource_id, $body));
return Redirect::back();
}
public function deleteComment()
{
$comment = new Comment;
$user = Auth::user();
$id = Input::only('id');
$comment->where('user_id', $user->id)->where('id', $id)->first()->delete();
return Redirect::back();
}
}
I'm using a command bus, so my handler class looks like this:
public function handle($command)
{
$comment = $this->postRepository->leaveComment($command->user_id, $command->resource_id, $command->body);
return $comment;
}
That leaveComment()
method looks like this:
public function leaveComment($user_id, $resource_id, $body)
{
$comment = Comment::leavePostComment($resource_id, $body);
User::findOrFail($user_id)->comments()->save($comment);
return $comment;
}
The leavePostComment()
method in the Comment model looks like this:
public static function leavePostComment($resource_id, $body)
{
return new static([
'resource_id' => $resource_id,
'body' => $body
]);
}