FAST AUTOCOMPLETE SEARCH TERMS - RAILS
Bạn muốn làm một chức năng tìm kiếm thông minh, có thể hiển tự động hiển thị kết quả ngay khi đang gõ chữ và gọi ý các kết quả. Một chức năng tìm kiếm giống với Facebook có thể cho kết quả bao gồm cả User cả Group. Hãy tham khảo sample app dưới đây. Tạo sample app $ rails new ...
Bạn muốn làm một chức năng tìm kiếm thông minh, có thể hiển tự động hiển thị kết quả ngay khi đang gõ chữ và gọi ý các kết quả. Một chức năng tìm kiếm giống với Facebook có thể cho kết quả bao gồm cả User cả Group.
Hãy tham khảo sample app dưới đây.
Tạo sample app
$ rails new fast-autocomplete
Thêm gem
gem 'faker', github: 'stympy/faker' gem 'rack-contrib' gem 'soulmate', :require => 'soulmate/server'
Sau đó chạy bundle
Tạo 2 model: Noun và Verb
$ rails g scaffold noun name:string $ rails g scaffold noun name:string
Sau đó chạy migrate
rake db:migrate
File app/models/noun.rb
class Noun < ActiveRecord::Base after_save :load_into_soulmate before_destroy :remove_from_soulmate validates_uniqueness_of :name private def load_into_soulmate loader = Soulmate::Loader.new("nouns") loader.add("term" => name, "id" => self.id, "data" => { "link" => Rails.application.routes.url_helpers.noun_path(self) }) end def remove_from_soulmate loader = Soulmate::Loader.new("nouns") loader.remove("id" => self.id) end end
File app/models/verb.rb
class Verb < ActiveRecord::Base after_save :load_into_soulmate before_destroy :remove_from_soulmate validates_uniqueness_of :name private def load_into_soulmate loader = Soulmate::Loader.new("verbs") loader.add("term" => name, "id" => self.id, "data" => { "link" => Rails.application.routes.url_helpers.verb_path(self) }) end def remove_from_soulmate loader = Soulmate::Loader.new("verbs") loader.remove("id" => self.id) end end
Tạo dữ liệu trong file seeds.rb
# create 500 nouns puts "Creating 'nouns'" 500.times do Noun.create(name: Faker::Name.name) end # create 500 verbs puts "Creating 'verbs'" 500.times do Verb.create(name: Faker::Name.name) end
Sau đó chạy
$ rake db:seed
File config/routes.rb
Rails.application.routes.draw do mount Soulmate::Server, :at => "/autocomplete" resources :verbs resources :nouns end
Ta có thể query soulmate bằng đường dẫn /autocomplete.
Ví dụ:
- Với đường dẫn: http://loacalhost:3000/autocomplete. Ta có thể thấy trạng thái của soulmate
- Với đường dẫn: http://0.0.0.0:3000/autocomplete/search?types[]=nouns&limit=6&term=pro ta được
Thêm //= require jquery.soulmate trong file app/assets/javascripts/application.js
//= require jquery //= require jquery_ujs //= require jquery.soulmate //= require turbolinks //= require_tree
Thêm *= require soulmate trong app/assets/stylesheets/application.css
*= require_tree . *= require soulmate *= require_self */
Thêm file soulmate.js trong app/assets/javascripts
var ready = function(){ var render, select; render = function(term, data, type) { return term; } select = function(term, data, type){ // populate our search form with the autocomplete result $('#search').val(term); // hide our autocomplete results $('ul#soulmate').hide(); // then redirect to the result's link // remember we have the link in the 'data' metadata return window.location.href = data.link } $('#search').soulmate({ url: '/autocomplete/search', types: ['users','groups'], renderCallback : render, selectCallback : select, minQueryLength : 2, maxResults : 5 }) } // when our document is ready, call our ready function $(document).ready(ready); // if using turbolinks, listen to the page:load event and fire our ready function $(document).on('page:load', ready);
Thêm file soulmate.css app/assets/stylesheets
#soulmate { background-color: #fafafa; border: 1px solid #bbb; display: none; font: 12px/14px "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: normal; list-style: none; margin: 0 0 0 10px; padding: 0; position: absolute; text-shadow: 0 0 0 white; /* play around with the top and left properties for correct positioning */ top: 201px; left: 460px; awidth: 579px; z-index: 1000; -webkit-border-radius: 4px; -moz-border-radius: 4px; -ms-border-radius: 4px; -o-border-radius: 4px; -khtml-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); -moz-box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); -khtml-box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); -ms-box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); -o-box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); } #soulmate .soulmate-type-container { border-top: 1px solid #ddd; } #soulmate .soulmate-type-container:first-child { border-top: none; } #soulmate .soulmate-type-suggestions { border-left: 1px solid #ddd; float: right; list-style: none; padding: 5px 0; awidth: 490px; letter-spacing: 0.5px; } #soulmate .soulmate-suggestion { color: #111; cursor: pointer; font-weight: 500; font-size: 13px; padding: 5px 0 6px 12px; text-decoration: none; } #soulmate .soulmate-suggestion.focus { color: white; margin-left: -1px; margin-right: -1px; padding-left: 13px; position: relative; text-shadow: 0 1px 1px #32629b; z-index: 1; -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); -khtml-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); -ms-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); -o-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); background: #545454; background: -moz-linear-gradient(top, #545454 0, #444444 100%); background: -webkit-gradient(linear, 0 0, 0 100%, from(#545454), to(#444444)); -ms-filter: "progid: DXImageTransform.Microsoft.gradient(startColorstr=#545454,endColorstr=#444444)"; filter: progid: DXImageTransform.Microsoft.gradient(startColorstr=#545454,endColorstr=#444444); } #soulmate .soulmate-type { background-color: white; color: #333; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 11px; letter-spacing: 0.5px; margin-right: 490px; padding: 10px 10px 0 10px; text-align: right; text-transform: capitalize; vertical-align: top; -webkit-border-radius: 5px; -moz-border-radius: 5px; -ms-border-radius: 5px; -o-border-radius: 5px; -khtml-border-radius: 5px; border-radius: 5px; zoom: 1; } #soulmate .soulmate-type:before, #soulmate .soulmate-type:after { content: ""; display: table; } #soulmate .soulmate-type:after { clear: both; }
Cuối cùng là cần file jquery.soulmate.js trong app/assets/javascripts jquery.soulmate.js
Tạo controller home/index
$ rails g controller home index
Thêm trong file routes.rb
root 'home#index'
Thêm view app/views/home/index.html.erb
<div class="container"> <h2>Search Nouns and Verbs</h2> <%= form_tag do %> <%= text_field_tag "search", nil, placeholder: "Search", autocomplete: :off %> <% end %> </div>
Thêm css cho view
home.css.scss
// Place all the styles related to the home controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ .container { awidth: 500px; margin: 0 auto; padding: 100px; text-align: center; } #search{ awidth: 400px; padding: 10px; } li.soulmate-suggestion{ text-align: left; }
Ta được form search như sau:
Để hiển thị kết quả tìm kiếm ta thêm file home.js
var ready = function(){ var render, select; render = function(term, data, type) { return term; } select = function(term, data, type){ // populate our search form with the autocomplete result $('#search').val(term); // hide our autocomplete results $('ul#soulmate').hide(); // then redirect to the result's link // remember we have the link in the 'data' metadata return window.location.href = data.link } $('#search').soulmate({ url: '/autocomplete/search', types: ['nouns','verbs'], renderCallback : render, selectCallback : select, minQueryLength : 2, maxResults : 5 }) } // when our document is ready, call our ready function $(document).ready(ready); // if using turbolinks, listen to the page:load event and fire our ready function $(document).on('page:load', ready);
Khi đó sẽ hiển thị được các kết quả mà ta muốn.
- Tài liệu: http://josephndungu.com/tutorials/fast-autocomplete-search-terms-rails
- Source code: https://github.com/phonghenry14/fast-autocomplete