Autocomplete with jQuery in Rails

Autocomplete is very useful so why not add it your site using jQuery? There is a neat part of the latest jQuery UI that does it all very easily.

There is a autocomplete rails plugin made by DHH. So why use this one?

  • jQuery is unobtrusive, better and you will be one of the cool guys using jQuery. The rails prototype helpers will add a bunch of onclick code to the html elements, not very elegant. And if you wants to do more than what the helpers offers you are stuck with some code in rails and some code with pure javascript which makes it harder to maintain the code.
  •  

  • jQuery autocomplete can use id as value instead of just the name. The autocomplete prototype plugin uses only value making it useless if you have duplicate values (i.e. cities with same name) or want to present the selection text as something more than the value itself (i.e. city, country).
  •  

  • More options. Better styling out of the box.

Anything wrong with the jQuery autocomplete plugin?

  • Data input support. No JSON. No XML. No CSV. Both are using non-standard data formats. jQuery UI autocomplete is using pipe-separated values while Prototype plugin uses a html list. Should at least be possible to specify value/text delimiter.
  •  

  • It is in beta but does not seem to be under development. Still has bugs if you use some of the extended options. No indication whether it is still under development.
  •  

  • The jQuery UI lists autocomplete as one of the feautres included. However the example uses the jQuery autocomplete plugin and the source code in jQuery UI autocomplete and the jQuery autocomplete plugin is different. In this example I have used the code in the latest jQuery UI
  •  

What you need

jQuery
jQuery UI beta

Remember to use the minified versions in production.

How it works

 

In Rails

Make sure your controller will respond to javascript (or whatever format you prefer to respond with).

The index action in CitiesController must be set up to search for the query paramater (q) and to respond with the javascript format:

def index
@cities = City.find(:all,:conditions => ['name LIKE ?', "#{params[:q]}%"],  :limit => 5, :o rder => 'name')
respond_to do |format|
format.html # index.html.erb
format.xml  { render :x ml => @cities }
format.js # index.js.erb
format.json { render :json => @cities }
end
end

Create the index.js.erb view file under views/cities

<% for city in @cities -%>
<%= city.name %>, <%= city.country.name %> |<%= city.id %>
<% end -%>
On the client

Write javascript/stylesheets in the HEAD section in your layouts/application.html.erb:

<%= yield :head %>

Include the required files (i.e. views/cities/index.html.erb):

<% content_for :head do %>
<%= javascript_include_tag 'jquery-1.2.6.min', 'jquery.ui-1.6rc2/ui/minified/ui.core.min', 'jquery.ui-1.6rc2/ui/minified/ui.autocomplete.min' %>
<%= stylesheet_link_tag 'jquery.ui-1.6rc2/themes/default/ui.all' %>

<script type="text/javascript">
$(document).ready(function(){
jQuery.ajaxSetup({
'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")}
})
$("#q").autocomplete( {
url : '<%= formatted_cities_path(:js) %>',
mustMatch : false
}
);
$("#q").autocomplete('result', function(event, data, formatted) {
if (data)
document.location.href = '/cities/' + data[1];
});
});
</script>
<% end%>

And finally the form on the same page:

<% form_tag cities_path, :method => 'get' do %>
<%= text_field_tag :q, params[:q] %>
<%= submit_tag "Locate city", :name => nil %>
<% end %>

About this entry