12/08/2018, 13:42

Ransack với ajax cho tìm kiếm autoload.

Phần mở đầu Tìm kiếm là một phần không thể thiếu trong mỗi trang web. Để tạo sự thoải mái nhất cho người dùng, chúng ta nên hiển thị kết qủa tìm kiếm tự động ngay sau khi người dùng nhập bất kỳ 1 từ khóa gì. Bài viết này sẽ hướng đẫn về cách để tìm kiếm như vậy. Phần 1: phân trang với gem ...

Phần mở đầu

Tìm kiếm là một phần không thể thiếu trong mỗi trang web.

Để tạo sự thoải mái nhất cho người dùng, chúng ta nên hiển thị kết qủa tìm kiếm tự động ngay sau khi người dùng nhập bất kỳ 1 từ khóa gì.

Bài viết này sẽ hướng đẫn về cách để tìm kiếm như vậy.

Phần 1: phân trang với gem will_paginate

 #gemfile

 gem "will_paginate", "3.1.0"
 gem "bootstrap-will_paginate", "0.0.10"
 #run bundle

sau đó thêm paginate cho controller và view

 #app/controllers/users_controller.rb

  def index
    @users = User.paginate page: params[:page],
      per_page: Settings.size_user
  end
#app/views/users/index.html.erb

....
<ul class="row users">
  <%= render @users %>
</ul>

<div id="infinite-scrolling">
  <div class="loading" hidden>
    <i class="fa fa-spinner fa-pulse fa-2x fa-fw"></i>
    <span class="sr-only"><%= "Loading" %></span>
  </div>
  <div hidden><%= will_paginate %></div> #ẩn nút paginate đi khi tự động load
</div>
#app/views/users/_user.html.erb

<li>
  <%= gravatar_for user, size: Settings.size_gravatar %>
  <%= link_to user.name, user %>
</li>

Phần 2: tự động load thêm trang khi scoll xuống cuối trang

add JS bắt sự kiện scroll cuối trang

 #app/assets/javascripts/pagination.js

 $(document).on('turbolinks:load', function() {
  if ($('#infinite-scrolling').size() > 0) {
    $(window).on('scroll', function() {
      var more_posts_url;
      more_posts_url = $('.pagination .next a').attr('href');

      if (more_posts_url && $(window).scrollTop() > $(document).height() - $(window).height() - 60) {
        $('.loading').show();
        $.getScript(more_posts_url);
        return;
      }
    });
  }
});

sau đó thêm khai báo file js

 #app/assets/javascripts/application.js

 //= require pagination.js

application.js sẽ bắt sự kiện khi có scoll và khoảng cách của thanh scroll với đáy trang < 60px. Nhờ đó, nó render ra link trong thanh a.href của pagination tức là users?page=2.

từ đây ta có thể truy vấn dữ liệu page 2 và ghép nó thêm vào cuối trang.

#app/controllers/users_controller.rb

  def index
    @users = User.paginate page: params[:page],
      per_page: Settings.size_user
    respond_to do |format|
      format.html
      format.js
    end
  end
#app/view/users/index.js.erb
$(".users").append(
  "<%= j render @users %>"
  );
$(".loading").hide();
<% if @users.next_page %>
  $(".pagination").replaceWith("<%= j will_paginate %>");
<% else %>
  $(window).off("scroll");
<% end %>

Phần 3: add gem ransack to search and auto load when user type character

#gem
gem "ransack"
#bundle
#app/views/users/index.html.erb

<div class="center row" id="search-form">
  <%= text_field_tag :q, nil,
    class: "form-control search-form",
    placeholder: "Search ..." %>
</div>

<ul class="row users">
 <%= render @users %>
</ul>
....

sau khi them text_field nhận từ khóa nhập vào từ người dùng, ta xử lý sự kiện người dùng gõ ký tự bất kỳ.

Và render lai view.

#app/assets/javascripts/user.js

$(document).on("turbolinks:load", function() {
  $(".search-form").on("keyup", function() {
    $(".users").html("");
    $.getScript("/users?q=" + this.value);
  });
});
#app/assets/javascripts/application.js

...
//= require user.js
#app/controller/users_controller.rb

@users = User.all.ransack(name_cont: params[:q]).result
  .paginate page: params[:page], per_page: Settings.size_user

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

Cuối cùng ta cần autoload thêm trang sau khi search

#app/assets/javascripts/user.js
$(document).on("turbolinks:load", function() {
  $(".search-form").on("keyup", function() {
    $(".users").html("");
    if ($("#infinite-scrolling").size() > 0) {
      $(window).on("scroll", function() {
        var more_posts_url;
        more_posts_url = $(".pagination .next a").attr("href");

        if (more_posts_url && $(window).scrollTop() > $(document).height() - $(window).height() - 60) {
          $(".loading").show();
          $.getScript(more_posts_url);
          return;
        }
      });
    }
    $.getScript("/users?q=" + this.value);
  });
});
ình

Cám ơn đã đọc bài viết của mình

0