2015-10-19 2 views
0

Это может быть немного запутанным, но я сделаю все возможное, чтобы объяснить, чего я пытаюсь достичь.jQuery: список комментариев исчезает при отправке формы ajax

У меня есть форма комментариев на каждой странице, пользователи могут отправлять комментарии через форму ajax, и представленный комментарий будет отображаться ниже формы без перезагрузки страницы.

Все это работает, пока я не представлю комментарии для показа на основе их post_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 (в закрыть окно ответа)

EDIT: Я думаю, что нашел проблему. в comment.js функция comment_done_handler() не возвращает никаких данных.

Так что если я прокомментирую $('.comment-list').html(data.comment_list);, список комментариев не будет исчезать при новом представлении. Но, конечно, недавно добавленный комментарий не отображается, пока я не перезагружу страницу.

EDIT 2: на самом деле это data.comment_list, что возвращается пустой в методе comment.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> 

Пожалуйста, обратите внимание, что если удалить из Comment модели, она начнет работать и перезагружает правильно comment_list с вновь добавленным комментарием.

Надеюсь, это имеет смысл и показывает проблему, с которой я сталкиваюсь.

+0

как насчет 'где ('post_id', $ postId) -> get()'; – manix

+0

Это дает ошибку «Отсутствует аргумент 1 для Illuminate \ Support \ Collection :: get(), вызванный в Comment.php' – Halnex

+0

Можете ли вы также отправить метод child_comments? –

ответ

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 не возвращает объект построителя запросов, он возвращает коллекцию. Вам нужно удалить вызов get() из child_comments и вместо этого использовать только get(), когда вы полностью состроили свой запрос.

Кроме того, ознакомьтесь с query scopes, который является гораздо более приятным способом выполнения того, что вы пытаетесь сделать.

Edit 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(); 
} 

Теперь они оба возвращающие коллекции, как вы ожидали бы. И вы можете повторно использовать эти области в другом месте, когда вам нужно восстановить записи комментариев.

Edit 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') 
    //... 
} 
+0

удаление 'get()' из 'child_comments()' полностью удалит comment_list. Моя проблема связана с предложением where в 'root_comments()', если я удалю его, comment_list перезагрузится с новым комментарием. Вы можете проверить приложение локально здесь https://github.com/Halnex/laravel-reddit – Halnex

+0

@Halnex - я обратился к этому. Вам все равно нужно использовать 'get()'. Он находится в неправильном месте и нарушает ваш вызов 'root_comments(), поэтому данные из этого вызова отсутствуют. Вы эффективно выполняете это: 'self :: where ('parent_id', $ parent_id) -> orderBy ('created_at', $ order) -> get() -> где ('post_id', $ postId); не собираюсь давать вам результаты, которые вы хотите. Вызов 'get()' должен быть в конце, но это не так. – lookitsatravis

+0

Я просто удалил 'get()' из child_comments и добавил его root_comments, ничего не изменилось, в комментарии отправить список исчезает. – Halnex

0

EDIT:

Попробуйте это:

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(); 
} 
+0

Но он извлекает его просто отлично, если я удаляю предложение where в 'root_comments()', вы уверены, что это так? – Halnex

+0

Проверьте мой отредактированный ответ, кажется, вы забыли добавить '-> get()' method – dede

+0

Добавление 'get()' будет проходить через ошибку при загрузке страницы. Я пытаюсь добавить запрос ajax get внутри 'comment_done_handler', но он говорит' request' undefined. поэтому я добавил свои поля. Теперь я получаю «GET/posts/comment_list» commenter_parent = 0 & commenter_post = 1 & commenter_comment = test 500 (Internal Server Error) 'с' Division By Zero'. – Halnex

Смежные вопросы