jQuery:评论列表在ajax表单提交时消失

时间:2015-10-19 16:50:58

标签: php jquery ajax laravel laravel-5

这可能有点令人困惑,但我会尽力解释我想要实现的目标。

我在每个帖子页面都有一个评论表单,用户可以通过ajax表单提交评论,提交的评论将显示在表单下方,无需重新加载页面。

所有这一切都有效,直到我根据他们的post_id和我正在查看的当前帖子ID指示评论显示。

当我这样做时,每个帖子都会开始只显示其评论,但当我尝试提交评论时,comment_list.blade.php会加载一个空的评论列表,而不是将新评论添加到现有评论中。我必须手动刷新页面才能看到评论。

我对评论有4个观点:

  • leave_a_comment.blade.php(有2个包含到comment_fields和 comment_list)
  • comment_fields.blade.php(评论表)
  • comment_list.blade.php(评论列表)
  • cancel_reply.blade.php(to 关闭回复窗口)

编辑:我认为我发现了问题。在comment.js comment_done_handler()函数中没有返回任何数据。

因此,如果我评论$('.comment-list').html(data.comment_list);,则评论列表在新提交时不会消失。但当然,在我重新加载页面之前,新添加的评论是不可见的。

编辑2:实际上它data.comment_listcomment.js comment_done_handler(数据)方法中返回为空。

comment.js

$(document).on('click', 'a.post-this-comment', function(){
    var form_data = {
        'per_page': $('.comments_per_page').val(),
        'commenter_parent': $('#commenter_parent').val(),
        'commenter_post': $('#commenter_post').val(),
        'commenter_comment': $('#commenter_comment').val(),
        'postid': $('#postid').val(),
    };

    var arr = [
        'commenter_parent',
        'commenter_post',
        'commenter_comment',
        'postid'
    ];

    for (var i in arr, i < arr.length, i++) {
        var elem = arr[i];
        form_data[elem] = $('#' + elem).val();
    }

// console.log(form_data); // something like => Object {per_page: "some_value", commenter_parent: "some_value", commenter_user_id: "some_value", commenter_comment: "some_value"}

    var request = $.ajax({
        type: 'POST',
        url: 'post_this_comment',
        data: form_data,
        dataType: 'json'
    });

    request.done(comment_done_handler);
    request.fail(comment_fail_handler);
});

function comment_done_handler(data){
    console.log(data); // data is sent from server
    $('.comment-content').append($('.reply-content .comment-fields'));
    $('.comment-list').html(data.comment_list); // put new list
    $('#captcha-image').attr('src', data.captcha); // put new captchas
    clear_input_fields();
    remove_error_messages(data);
    hide_comment_fields();
}

Comment模型

public static function root_comments($postId) {
    return self::child_comments(0, 'desc')->where('post_id', $postId);
}

public static function child_comments($parent_id, $order='asc'){
    return self::where('parent_id', $parent_id)->orderBy('created_at', $order)->get();
}

public function posts() {
    return $this->belongsTo('App\Post');
}

public function user() {
    return $this->belongsTo('App\User');
}

CommentController

protected function comment_list($per_page, Request $request, Post $post) {
    $postId = $post->id;
    $root_comments = Comment::root_comments($postId);
    $root_with_replies = $this->include_replies_for($root_comments);
    $paginated_comments = $this->paginate($root_with_replies, $per_page, $request);
    return $paginated_comments;
}

public function index(Request $request, Post $post){
    $view_data = self::view_data($request, $post);
    return view('eastgate.comment.leave_a_comment', $view_data);
}

public static function view_data(Request $request, Post $post) {

    $instance = new Self;
    $per_page = session('per_page')?session('per_page'):config('constants.per_page'); // default per page on opening the comment page
    $result['per_page'] = $per_page;
    $result['comments'] = $instance->comment_list($per_page, $request, $post);
    $result['total_comments'] = $instance->total_comments();
    $result['captcha_builder'] = $instance->captcha_builder();
    return $result;
}

public function post_this_comment(Request $request, Post $post) {
    $comment = new Comment;
    $comment->user_id = Auth::id();;
    $comment->comment = Input::get('commenter_comment');
    $comment->post_id = Input::get('commenter_post');
    $comment->parent_id = Input::get('commenter_parent');
    if($comment->parent_id > 0){
        $my_parent = Comment::find($comment->parent_id);
        $comment->parents = $my_parent->parents.'.'.$comment->parent_id;
    }else{
        $comment->parents = '0';
    }
    $comment->save();
    $per_page = Input::get('per_page');
    $comment_list = view('eastgate.comment.comment_list')
                        ->with('comments', $this->comment_list($per_page, $request, $post))
                        ->with('total_comments', $this->total_comments())
                        ->with('per_page', $per_page)
                        ->render();
    $response = array(
        'status' => 'success',
        'msg' => 'Comment Saved!',
        'comment_list' => $comment_list,
        'captcha'   => $this->captcha_builder()->inline()
    );
    return Response::json($response);
}

comment_fields.blade.php

<div class="comment-fields">
    <div class="row commenter-comment">
        <div class="form-group col-md-12">
            <textarea id="commenter_comment" name="commenter_comment" class="form-control comment-field" title="User's comment" placeholder="Comment Text"></textarea>
        </div>
    </div>

    <div class="row commenter-name-email">
        <input type="hidden" id="commenter_parent" name="commenter_parent" class="commenter-parent" value="0">
        <input type="hidden" id="commenter_post" name="commenter_post" class="commenter-post" value="{{ $post->id }}">
    </div>

    <div class="row commenter-captcha">
        <div class="col-md-3">
            <a href="javascript:void(0)" class="btn btn-success post-this-comment">Comment</a>
        </div>
    </div>
</div>

comment_list.blade.php

<div class="comment-list">
    <div class="row">
        <div class="col-xs-12"> 
            <h2>{!! $total_comments !!} comment(s) </h2>

            @foreach($comments as $each_comment)
                <?php 
                    $name_for_display = $each_comment->user->name;
                    $date_for_display = $each_comment->created_at->diffForHumans();
                    $parent_name_for_display = '';
                    if($each_comment->parent_id > 0){
                        $parent_comment = $each_comment->parent();
                        $parent_name_for_display = $parent_comment != null && $parent_comment->name
                                                    ? $parent_comment->name : 'Anonymous';
                        $parent_name_for_display = '<span class="glyphicon glyphicon-share-alt" title="Reply to">&nbsp;</span>'.$parent_name_for_display;
                    }
                    $parents_count = substr_count($each_comment->parents, '.');
                    $offset_length = $parents_count;
                    $comment_length = 12 - $offset_length;
                ?>
                <div class="col-xs-offset-{!! $offset_length !!} col-xs-{!! $comment_length !!}">
                        <input type="hidden" id="postid" name="postid" class="post-id" value="{{ $each_comment->post_id }}">
                    <ul class="list-inline">
                        <li class="comment-by">{!! $name_for_display !!}</li>
                        @if($parents_count > 0)
                            <li class="reply-to">{!! $parent_name_for_display !!}</li>
                        @endif
                        <li class="separator"></li>
                        <li class="comment-on">{!! $date_for_display !!}</li>
                    </ul>

                    <p>{!! $each_comment->comment !!}</p>

                    <a href="javascript:void(0)" class="reply comment{!! $each_comment->id !!}" title="Reply to above comment">Reply</a>

                    <div class="reply-content reply{!! $each_comment->id !!}"></div>

                    <hr>
                </div>
            @endforeach
        </div>
    </div>
    <div class="row">
        <div class="col-xs-12">
            {!! $comments->render() !!}
        </div>
    </div>
    <div class="row">
        <div class="col-xs-12">
            Show <input type="text" name="comments_per_page" class="comments_per_page" value="{!! $per_page !!}" size="2" title="Number of comments per page"> comments per page
        </div>
    </div>
</div>

请注意,如果我从where('post_id', $postId)模型中移除Comment,它将开始工作,并使用新添加的评论重新加载正确的comment_list

我希望这是有道理的,并表明我面临的问题。

2 个答案:

答案 0 :(得分:1)

我没有尝试执行代码,但这是可疑的:

public static function root_comments($postId) {
    return self::child_comments(0, 'desc')->where('post_id', $postId);
}

public static function child_comments($parent_id, $order='asc'){
    return self::where('parent_id', $parent_id)->orderBy('created_at', $order)->get();
}

root_comments(在控制器的comment_list操作中引用)链接child_comments。除了child_comments不返回查询构建器对象,它返回一个集合。您需要从child_comments中移除get()来电,而只需在完成构建查询后使用get()

另外,查看query scopes,这是一种更好的方式来完成你想要做的事情。

编辑1 - 示例(使用范围):

  

我没有运行此代码,因此存在语法错误。这是为了更好地解释这个概念。

//First, you need to create scopes on the model
public function scopeByParent($query, $parentId, $order = 'asc') {
    return $query->where('parent_id', $parentId)->orderBy('created_at', $order);
}

public function scopeForPost($query, $postId) {
    return $query->where('post_id', $postId);
}

//Then, change your existing methods...
public static function root_comments($postId) {
    return self::byParent(0, 'desc')->forPost($postId)->get();
}

public static function child_comments($parent_id, $order = 'asc') {
    return self::byParent($parent_id, $order)->get();
}

现在这些都是你期望的回归集合。当您需要检索注释记录时,可以在其他地方重用这些范围。

编辑2:

以上是问题的一部分。问题的第二部分是您从未检索过发布评论的帖子。我在本地做了这个改变,它开始起作用了:

public function post_this_comment(Request $request, Post $post) {

    //...
    $per_page = Input::get('per_page');

    //After line 148. The $post that is created by the IoC container is just a reference to the class. You still must load the post from the DB to get the proper data from it.
    $post = $post->find($request->commenter_post);

    $comment_list = view('eastgate.comment.comment_list')
    //...
}

答案 1 :(得分:0)

修改

试试这个:

public static function root_comments($postId) {
    return self::child_comments(0, 'desc')->where('post_id', $postId)->get();
}

- 编辑前---

您的comment_done_handler无法获取新创建的评论列表。 你应该在里面做另一个ajax请求,或者作为一个单独的函数

function comment_done_handler(data){
     var data = $.ajax({
        // ......
       // params sent for this request to comment_list controller method
        data: {
              per_page: 10,
              request: request,
              post: post_id
        },

        type: 'GET',
        url: 'comment_list'
        // ......

    }).done(function() {
       // ....
    }).fail(function(){
      // ....
    });

    console.log(data); // data is retrieved from server
    $('.comment-content').append($('.reply-content .comment-fields'));
    $('.comment-list').html(data.comment_list); // put new list
    $('#captcha-image').attr('src', data.captcha); // put new captchas
    clear_input_fields();
    remove_error_messages(data);
    hide_comment_fields();
}