simple auto complete text field
Posted in blog on Mar 26. Tags: ajax, auto complete, Ruby on Rails, simple, text_field_with_auto_complete
I have been working on understanding the text_field_with_auto_complete functionality in Ruby on Rails for a project I am currently working on. There seems to be two written tutorials on the subject and they were a little confusing. Here is my attempt to be more specific.
Goal:
While editing an address record I want to show the user a short list of available suburbs that match what they have begun typing into he text box; and allow them to pick the one they want to use. When they save the record, I only want to store the ID of the suburb they typed in, not the actual text.
Solution:
Install the auto_complete gem:
ruby script/plugin install git://github.com/rails/auto_complete.git
This didn’t work on the windows system I was using, so I ended up having to grab the ZIP file and copy the contents to the ‘vendor/plugins/auto_complete’ folder the above command created.
First of all add to the site.rb model so we can refer to the suburb_name as if it was a field in the sites table:
def <span style="color: #ff00ff;">suburb_name</span>
<span style="color: #00ccff;">suburb.name</span> if <span style="color: #ff6600;">suburb_id</span>
end
def <span style="color: #ff00ff;">suburb_name</span>=(value)
self.<span style="color: #ff6600;">suburb_id</span> = Suburb.find_by_name(<span style="color: #ff0000;">value.split(',')[0]</span>).<span style="color: #000000;">id</span> unless value.blank?
end
Update the sites/edit.html.erb view to do the auto_complete markup:
<p>
<%= f.label :<span style="color: #ff6600;">suburb </span>%><br />
<%= text_field_with_auto_complete <span style="color: #993366;">:site</span>, :<span style="color: #ff00ff;">suburb_name</span>, {}, :skip_style => false %>
</p>
Add an action to the sites_controller.rb so the auto_complete call(s) can get the short list:
def auto_complete_for_<span style="color: #cc99ff;">site</span>_<span style="color: #ff00ff;">suburb_name</span>() <span style="color: #0000ff;">@suburbs</span> = Suburb.find(:all , :conditions=> "<span style="color: #33cccc;">name </span>like '%"+params[<span style="color: #993366;"><span style="color: #000000;">:</span><span style="color: #cc99ff;">site</span></span>][:<span style="color: #ff00ff;">suburb_name</span>].upcase+"%' and we_deliver_to=1") render :partial => '<span style="color: #99cc00;">auto_complete_</span><span style="color: #ff00ff;">suburb_name</span>' end
Finally, create the _auto_complete_suburb_name.html.erb partial in the views/sites folder, the smallest form of which is like this
<ul><% for suburb in <span style="color: #0000ff;">@suburbs</span> do %><li><%=h <span style="color: #00ccff;">suburb.name</span> %><span style="color: #ff0000;">, </span><%=h suburb.postcode %></li><% end %></ul>
Important stuff you should know
- I have added highlighting to illustrate the important connections between names as you move between view/model/controller. If you change one, you need to make the same change in every other occurence.
- The suburbs table has no duplicates across the [name] field and no commas in any name value.
- The COMMA in the partial is vitally important, I use it to tell the difference between the name value and the rest of the information that I don’t care about (the postcode). Use your own unique seperator if you have comma’s in your data.
- No spaces in the _auto_complete_suburb_name partial, if you format it nicely your selected result will have lots of extra spaces (you’ll see what I mean)
- There is no error checking in this. If the user types in a junk suburb the current code will not handle it gracefully.
