What is jQuery autocomplete?
The jQuery autocomplete plugin enables your users to receive suggestions while they type keywords in an input field.
How do you use it with elasticsearch?
If you haven’t setup elasticsearch with your Rails application, you can read about how to do it in these articles:
- How To Install Elasticsearch On Linux for Rails Development
- How To Setup Elasticsearch In Your Rails Application In Development
- How to Setup Elasticsearch in your Rails App in Production
Step 1 – Install rails gem
Add the jquery-ui-rails to your Gemfile and run bundle install.
gem 'jquery-ui-rails'
At the command line type:
bundle install
Step 2 – Require the correct assets in your asset pipeline
Here I will show how I have my assets setup, but you can see the jquery-ui-rails README on github if you want to pick and choose what parts of jquery-ui you want to include.
In your application.css file, include the following assets:
//= require jquery-ui/core
//= require jquery-ui/theme
*= require_self
In your application.js file, include the following:
//= require jquery
//= require jquery_ujs
//= require jquery-ui
//= require_tree .
Step 3 – Write a controller method
class AjaxController < ApplicationController
respond_to :json
def autocomplete
# ...
@response = HTTParty.get("http://scctsi-ctds-staging.herokuapp.com/1/clinical\_trials/layman\_terms")
@tag_counts = @response["response"] if params[:term] @tag_counts = @tag_counts.select { |term, value| term=~/#{params[:term]}.\*/}
respond_with(@tag_counts)
end
end
In the controller above, I am calling out to an API (basically another Rails application) that returns a JSON response with a disease name and a count like the following:
{"response":{"Kidney (Renal Cell) Cancer":6,"Advanced or
Metastatic":4,"Localized or Resected":4,"Heart Attack":17,"Rheumatic
Diseases":16,"Alzheimer’s Disease":8,"Dementia":6,"HIV":2,"AIDS":2,"Hepatitis c":2,"HIV and
aging":2,"HIV/hepatitis c co-infection":2,"Bladder (Urothelial,
Transitional Cell) Cancer":4,"Aneurysm":2,"Stroke":2,"Cerebrovascular
Disease":1,"Cerebrovascular Stroke":1,"Cerebrovascular Accident":1,"Skin
(Cutaneous) Cancer":3,"Squamous Cell":3,"Head and Neck
Cancers":1,"Hypopharynx":1,"Larynx":1,"Lip Nasopharynx":1,"Oral
Cavity":1,"Oropharynx":1,"Trachea":1,"Aortic Disease":3,"Aortic
Stenosis":5,"Heart Failure":7,"Heart Valve
Diseases":5,"Uterine/Endometrial Cancer":5,"Metastatic or
Unresectable":2,"Resectable (Pre-Cystectomy)":2,"Superficial
(Non-Invasive)":2,"Bone Cancer":5,"Ewing’s
Sarcoma":5,"Osteosarcoma":5,"Non-Small Cell Cancer (NSCLC)":6,"Small
Cell Lung Cancer (SCLC)":6,"Pancreatic
Cancer":2,"Narcolepsy":1,"Leukemia":5,"Acute Lymphoid leukemia
(ALL)":5,"Acute Myeloid Leukemia (AML)":5,"Acute Promyelocytic Leukemia
(APL)":5,"Chronic Lymphocytic Leukemia (CLL)":5,"Chronic Myelogenous
Leukemia (CML)":5,"Other Leukemia":5,"Lymphoma: Hodgkin":4,"Lymphomas:
Non-Hodgkin":4,"Cutaneous Lymphoma":4,"Diffuse Large B-Cell
Lymphoma":4,"Low Grade Lymphoma":4,"Mantle Cell Lymphoma":4,"Other
Histologies":4,"T-Cell Lymphoma":4,"Waldenstrom
Macroglobulinemia":4,"Gynecologic Cancers":2,"Eye Cancer":1,"High Blood
Pressure / Hypertension":2,"Pulmonary Hypertension":1,"Basal Cell
Carcinoma":1,"Melanoma":1,"Other Skin Cancers":1,"Multiple
Sclerosis":2,"Glaucoma":1,"Arrhythmias":1,"Atherosclerosis":2,"Thrombosis":1,"Arthritis":2,"Liver":3,"Ovarian/Peritoneal/Fallopian
Cancer":1,"Neuroendocrine Tumors":5,"Diabetes":2,"Huntington’s
Disease":16,"Parkinson’s Disease":16,"Tourette’s Disorder":13,"Brain
(Central Nervous System) Cancers":15,"Gliomas":16,"Metastatic
CNS":13,"Pediatric Brain Tumors":13,"Central Nervous System
Cancer":15,"Liver Tumors":7,"Chronic Liver Disease / Cirrhosis":7,"Any
Cancer Condition or Solid Tumor":57,"Breast Cancer":19,"Lung
Cancer":18,"Stomach Cancer":19,"Gastric (Stomach)
Cancer":7,"Gastrointestinal Stromal Tumor (GIST)":7,"Colon/Rectal
Cancer":6,"Anal Cancer":6,"Colon Cancer":6,"Rectal Cancer":6,"Prostate
Cancer":4,"Localized Disease":4,"Metastatic Disease":4}}
The params[:term] tells the controller what term(s) (or disease name(s)) to display to the end user in the autocomplete search box. It works in real-time.
Step 4 – Include a route to the controller in routes.rb
get 'autocomplete', to: 'ajax#autocomplete'
Step 5 – Write a coffeescript method to call the search method
In my case, I wanted to display the count along with the disease name asthe user typed their search term. I also wanted the user to be able to mouse click on the terms as they were dropping down via autocomplete and have the Rails application respond to that event by bringing the user to a page with more information about that term. Hence, I tell the autocomplete widget to submit the form with the selected term value via the select api method of jQuery autcomplete.
jQuery ->
$('#search_terms').autocomplete
source: (request, response) ->
$.ajax
url: '/autocomplete.json'
dataType: "json"
data: { term: request.term }
success: (data) ->
objects = $.map(data, (v, i) ->
label: i+" ("+v.toString()+")"
value: i)
response objects
select: (event, ui) ->
$("#search_terms").val(ui.item.value)
$("#search-form").submit()
Step 6 – Setup the search form in your Rails view
You also have to setup the search form with the appropriate CSS id names that you reference in your coffeescript code. Below is what I used.
= form_tag(search_path, :method => "get", id: "search-form", class: "navbar-form navbar-left") do
= text_field_tag :search_terms, params[:search_terms], placeholder: "Search by Keyword", class: "form-control"
= submit_tag "Search", :name => nil, class: "btn btn-default"