5

用 ajax + paginate 讓留言功能更出色

 2 years ago
source link: https://blog.niclin.tw/2017/08/24/%E7%94%A8-ajax---paginate-%E8%AE%93%E7%95%99%E8%A8%80%E5%8A%9F%E8%83%BD%E6%9B%B4%E5%87%BA%E8%89%B2/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Nic Lin's Blog

喜歡在地上滾的工程師

Implement background animation colors for comments(like stack over flow share answer link)

Rails version 5.1.3 Ruby version 2.3.2

原本如果實作一個 Post has_many Comments 的 CRUD

最陽春的版本就是在留言之後,跳出一個 flash 顯示

「你已留言成功」

不過因為是用 http post,所以在 controller action 就會 redirect_to 一個 path 回來,

在這裡我們可以用

  • Rails 4 redirect_to :back
  • Rails 5 redirect_back(fallback_location: root_path)

來做到留言後返回同一頁。

不過看似沒有導去任何的頁面,但是頁面卻彈到最頂部了。

因為這其實是在重新 load 當前頁面。

所以當留言越來越長,我們每次留言完就會又彈回頂部。這樣實在太糟糕了

秉持著現代流行的 SPA 精神,我們用 ajax 來完成吧

目標讓留言系統有

  • Load more 按鈕載入更多留言
  • ajax 留言
  • 留言後下拉至留言處,並對留言區塊產生顏色漸層

對於漸層從亮色到底色這種標記區塊的方法,是從 StackOverFlow 分享 answer 裡面看到的,所以就思考了一下並實作,你可以點看看這個在 stackoverflow 經典的答案分享體驗一下。

Gem install

gem 'jquery-rails'
gem 'will_paginate', '~> 3.1'
//= require rails-ujs
//= require jquery

Load more 按鈕載入更多留言

CRUD 這邊就略過不贅述了 XD

在 post#show 顯示留言,直接先分頁


def show
    @comments = @post.comments.paginate(page: params[:page], per_page: 5).order('created_at DESC')

    respond_to do |format|
      format.html
      format.js
    end
end

先寫 helper

  def render_ajax_more_comments_link(post, comments)
    link_to("SHOW MORE", post_path(post, page: comments.next_page), remote: true, class: 'btn coin-comment__load-more-btn', id: "js-load-more-comments" )
  end

再 show 頁面使用這個 load more 按鈕,並且在 form 的地方補上 remote: true

// 留言表單獨立出來做 partial
<%= render "comment_form"%>

// Load more 按鈕
<% if @comments.next_page %>
  <div class="coin-comment__load-more">
     <%= render_ajax_more_comments_link(@post, @comments) %>
  </div>
<% end %>

comment form 的 partial

<%= simple_form_for [@post, Comment.new], remote: true, html: { id: 'js-comment-form' } do |f| %>

    <%= f.input :message %>

    <%= f.submit "COMMENT", class: "btn btn-sm", data: { disable_with: "COMMENT..." } %>
<% end %>

設定 js.erb

$('#js-comments-list').append("<%= j render @comments %>");

<% if @comments.next_page %>
  $('#js-load-more-comments').replaceWith('<%= j render_ajax_more_comments_link(@post, @comments) %>');
<% else %>
  $(window).off('scroll');
  $('#js-load-more-comments').remove();
<% end %>

Load more button 示範

ajax 留言

controller 在 create 留言時會紀錄哪位使用者留言的

  def create
    @post = Post.friendly.find(params[:post_id])
    @comment = @post.comments.build(comment_params)
    @comment.user = current_user

    respond_to do |format|
      if @comment.save
        format.html { redirect_to(post_path(@post)) }
        format.js
      else
        format.html { redirect_back(fallback_location: root_path) }
        format.js
      end
    end
  end

因為 create 行為沒有 html.erb ,不過要有 js 行為,所以

$('#js-comments-list').append("<%= j render @comment %>");

// clear form input 留言後能夠把 form 上面的 input 欄位清掉
$('#js-comment-form')[0].reset();

// scroll to bottom 依照當前網頁高度,去計算拉到底部的高度,這邊採用 jquery 裡面的 animate 實作
height = $('#js-comments-list').offset().top;
$('html, body').animate({scrollTop : height+ $('#js-comments-list').height()},500);

// comment moment height light 先給予顏色,之後再用 animate 將顏色動畫漸變回底色
$('#js-comments-<%= @comment.id %>').css("backgroundColor", "rgba(255, 210, 46, 0.39)");
$('#js-comments-<%= @comment.id %>').animate({backgroundColor: "#fff"}, 800);

由於原本的 jquery 是沒有加入 backgroundColor 的功能,這是額外的擴充,所以請在 layout 裡面加入

一定要在 javascript 載入之後再載入 jquery.color-animation ,因為他是依賴在 jquery 之下

    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
    <script src="//cdn.jsdelivr.net/jquery.color-animation/1/mainfile"></script>

記得做一塊 partial ,裡面是每一個 comment

<div id="js-comments-<%= comment.id %>">
  <%= comment.user.name %>
  <%= comment.message %>
</div>

這邊的 js-comments-<%= comment.id %> 用意是為了能夠辨別每一個唯一的 comment 加上的標籤,這樣一來,我們就可以做到留言後自動標記了

到這邊,應該可以實現如下圖的功能了


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK