RAILS auto_complete With Additional FILTER

Auto complete with additional filter

The best tutorial about auto complete control by far was one from Ryan Bates. It worked like a charm, and he made it look so easy. Only problem I had with it was that I wanted another control on the form to filter the auto-complete control.
The tutorial didn’t cover that, so I got stranded in a strange place. The solution was pretty simple, but it took me a while to figure it out. If you are just beginning Rails like I am – this is rigth tutorial for you.

I have ‘City’ and ‘Street’ on my form. ‘City’ is regular drop down list since there are only few cities to select from. I wanted the ‘Street’ control to be an autocomplete text box that get’s filtered based on the city that is selected. You need to do everything that Ryan says you should – when you finish his tutorial come back for adding “filter” functionality :) I’ll won’t add exactly the same fields, but you’ll get the point… Oh, you are back already… ok. I am assuming that you’ll change model names based on the model that you are using. I did everything in Ryan tutorial but with my model.
You need to pass additional parameter that you want to be a filter. In my case that is currently selected city id. I’ll put it in template ‘new.html.erb’ of view that is rendering both controls

<%= f.select  :settlement_id, @settlements.map {|u| [u.name,u.id]} %>
 <%= f.text_field_with_auto_complete :event, :street_name , {
 :url => formatted_streets_path(:js), :method => :get,
 :with =>"'search=' + element.value + '&settlement_id=' + $('event_settlement_id').value"  } %>

Step 1)

Pay attention to :with

:with =>"'search=' + element.value + '&settlement_id=' + $('event_settlement_id').value":

You are basicly saying : Append to url search=#value_of_my_control&settlement_id=#value_of_control_named_event_settlement_id

Step 2)

Change the street controller to know how to accept additional parameters and filter the results

def index

    if params[:settlement_id].blank?
      @streets = Street.find(:all,
                          :conditions => ['name LIKE ?', "%#{params[:search]}%"])
    else
      @streets = Street.find(:all,
                   :conditions => ['name LIKE ? and settlement_id = ?', "%#{params[:search]}%", "#{params[:settlement_id]}" ])
    end

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :x ml => @streets }
      format.js
    end
  end
 

You can check it out just by typing

http://localhost:3000/streets.js?search=mac&settlement_id=1 

to see if data fetching is working. After that the autocomplete should “just work”

That’s all for now…

  • Thanks for the tip. I was wondering how to do that.

    @ikanan: you only need custom routes if the ajax request goes to another controller than the one you are currently one (well the last rendered one).
  • lkanan
    Thanks for a quick response. My form regarding above question is actually user registration form. In the form there are fields, such as username, email, password, etc. and I also have select list for cities and a field for streets. What I'm trying to accomplish is auto completion for streets field(depending on a selected city). So I need to pass to my controller's action city_id and first street symbol(s). By default it would be handled by user's controller index action, but I don't think that's an appropriate place, so I would like to create another controller(let's say streets_controller) and an action in it(let's say auto_complete_for_street_name) and additionally pass to that method city_id. Any hints how that can be accomplished would be greatly appreciated.
  • Kresimir Bojcic
    I am not expert by any means... but scenario you are giving sounds good to me. Maybe this can help you out.
    First check out demo project http://gosjar.heroku.com/events/new and then you can check out the code here http://www.gitcentral.com/projects/gosjar/repos/mainline
  • lkanan
    I find this post very useful. I'm trying to accomplish a similar thing, however there are problems. Could You provide a corresponding route (from config/routes.rb) for the above example? Thanks in advance.
  • Kresimir Bojcic
    I didn't use custom routing, just "map.resources :streets", take notice that I've added format.js in respond_to method in index action of controller.
blog comments powered by Disqus