用 ajax + paginate 讓留言功能更出色
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.
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 加上的標籤,這樣一來,我們就可以做到留言後自動標記了
到這邊,應該可以實現如下圖的功能了
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK