Tag Type-Ahead with Multiple Items

If you’ve ever implemented type-ahead functionality and wondered how to get it to work when users are entering multiple items, like a list of comma delimited tags, here it is.

You can, of course, roll your own Javascript and Ajax calls but why bother when Rails gives us a nice Javascript helper to handle this. The helper is text_field_with_auto_complete but this defaults to the current controller. For my purposes tags can be entered on different areas of the site for different models so I used text_field_with_auto_complete with one modification:

  def text_field_with_auto_complete_with_custom_url(object, method, url_options = {}, tag_options = {}, completion_options = {})    (completion_options[:skip_style] ? "" : auto_complete_stylesheet) +    text_field(object, method, tag_options) +    content_tag("div", "", :id => "#{object}_#{method}_auto_complete", :class => "auto_complete") +    auto_complete_field("#{object}_#{method}", { :url => { :action => "auto_complete_for_#{object}_#{method}" }.update(url_options) }.update(completion_options))  end

Note: text_field_with_auto_complete is deprecated and will be moved to a plugin in Rails 2.0.

The third parameter is now a hash of optional url arguments (action, controller, etc). You can also monkey patch the original method or better use some alias/alias_method_chain trickery in your own app. In your view call the newly created helper with your arguments.

     "tagging_demo"}, {}, { :tokens => ','} %>

Include the necessary javascript libraries (prototype and scriptaculous):

You can set the controller and action to whatever you like but it defaults to a method in the form of auto_complete_for_object_method. Going with that your action could look something like this:

  def auto_complete_for_tag_names    @tags = Tag.find(:all,       :conditions => ["name like ?", "%#{params[:tag][:names]}%"],       :order => 'name DESC', :limit => 20)    render :layout => false  end

And your view (auto_complete_for_tag_names.html.erb):

That’s all there is to it. The magic comes from providing a token to Ajax.Autocompleter which we provided in the argument hash to text_field_with_auto_complete_with_custom_url ( { :tokens => ‘,’} ). You can use any delimiter you like. You can also customize the UI in your view and CSS.