Wolfmans Howlings

A programmers Blog about Ruby, Rails and a few other issues

Having multiple text_field_with_auto_complete in the same view

Posted by Jim Morris Wed, 18 Oct 2006 06:45:47 GMT

I ran into a problem using text_field_with_auto_complete in a view where I wanted to have many of them created by an iteration. You can use the :index option for the text_field, but it doesn't carry over to the various divs used in the AJAX calls.

<% 0.upto(10) do |legi|  %>
<% @leg= @mission.legs.find(:first, :conditions => ['legnum = ?', legi]) %>
text_field_with_auto_complete( :leg, :name, {:index => legi, :size => 20})
<% end %>
<% end %>

is what you really want to do, just as for a regular text_field.

I googled around and found this bug report for a fix to text_field_with_auto_complete that allows :index, as that fix does not appear to be in the current stable release of Rails or on Edge rails, I just created a my_text_field_with_auto_complete and it worked like a charm!!

  def my_text_field_with_auto_complete(object, method, tag_options = {}, completion_options = {})
    if(tag_options[:index])
      tag_name = "#{object}_#{tag_options[:index]}_#{method}"
    else
      tag_name = "#{object}_#{method}"
    end

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

So I put this in app/helpers/application_helper.rb and simply use my_text_field_with_auto_complete in my views.

Here is what the controller side looks like...

  def auto_complete_for_leg_name
    leg= params[:leg].keys[0] # get index as its always only one at a time
    auto_complete_responder_for_name params[:leg][leg][:name]
  end
...
private
  def auto_complete_responder_for_name(value)
    param= value.downcase + '%'
    find_options= {
      :conditions => [ 'LOWER(lname) LIKE ?', param ],
      :order => 'lname ASC',
      :limit => 6
    }
    @names = Person.find(:all, find_options)
    render :partial => 'names'
  end

Posted in  | Tags ,  | 18 comments | no trackbacks

Comments

  1. Kevin Olbrich said about 5 hours later:

    Nice work. One problem I see. When the parameters get serialized, you end up with something like {"object"=>{"index"=>"value"}} in the params, which confuses the standard auto_complete_for handler.

  2. Kevin Olbrich said about 5 hours later:

    Whoops, no. Actually it does work.

  3. wolfman said about 10 hours later:

    Good point I'll add the controller side of the code too, as it does work.

  4. kevin hutchison said 11 days later:

    Can i ask how the responder knows which partial to render? Or does it render all name partials?

    thanks much,h

  5. wolfman said 11 days later:

    kevin- it will render the partial called _names.rhtml in the relevant views directory. There is only one partial used in this case. Maybe I misunderstood your question?

  6. ThirtyTwo said 13 days later:

    Well done. Thank you.

  7. arun agrawal said 8 months later:

    thanks

  8. arun agrawal said 8 months later:

    i need a default value in text box when i came that page. and when i just delete the value manually and type another then the auto text will apppear

  9. Bala said 8 months later:

    I Tried this example i couldnt able to list the details but i can able to retrieve the datas what would be the problem? plz help me guyz, one of the requirements to my project.

  10. wolfmanjm said 8 months later:

    Can you email me the details? I don't really understand what problem you are having.

  11. Bala said 8 months later:
    Controller.

    def userautocomplete name= params[:user].keys[0] # get index as its always only one at a time responderautocompleteforuser_name(params[:user][name][:name]) end

    private def responderautocompleteforuser_name(value) param= '%' + value.downcase + '%' find_options= { :conditions => [ 'name like ?', param ], :order => 'name ASC', :limit => 60 }
    @names = User.find(:all, find_options) render :partial => 'names' #render :update do |page| #page['user1nameautocomplete'].show #page['user1nameautocomplete'].replace :partial => "names" #end end

    Application helper

    module ApplicationHelper

    def mytextfieldwithautocomplete(object, method, tagoptions = {}, completion_options = {}) if(tag_options[:index]) tagname = "#{object}#{tagoptions[:index]}#{method}" else tagname = "#{object}#{method}" end puts "Tag Name = > " + tag_name (completionoptions[:skipstyle] ? "" : autocompletestylesheet) + textfield(object, method, tagoptions) + contenttag("div", "", :id => tagname + "autocomplete", :class => "auto_complete") + autocompletefield(tagname, { :url => { :action => "autocompletefor#{object}#{method}" } }.update(completionoptions)) end

    def autocompletetextone(object, method, tagoptions = {}, completion_options = {}) if(tag_options[:index]) tagname = "#{object}#{tagoptions[:index]}#{method}" else tagname = "#{object}#{method}" end (completionoptions[:skipstyle] ? "" : autocompletestylesheet) + textfield(object, method, tagoptions) + contenttag("div", "", :id => tagname + "autocomplete", :class => "auto_complete") + autocompletefield(tagname, { :url => { :action => "userautocomplete" } }.update(completionoptions)) end

    def autocompletetexttwo(object, method, tagoptions = {}, completion_options = {}) if(tag_options[:index]) tagname = "#{object}#{tagoptions[:index]}#{method}" else tagname = "#{object}#{method}" end puts tag_name (completionoptions[:skipstyle] ? "" : autocompletestylesheet) + textfield(object, method, tagoptions) + contenttag("div", "", :id => tagname + "autocomplete", :class => "auto_complete") + autocompletefield(tagname, { :url => { :action => "autocompletefor" + tagname } }.update(completionoptions)) end

    end

    view file

    <% 1.upto(3) do |legi| %> <%=autocompletetext_one( :user, :name, {:index => legi, :size => 20}) %>





    <% end %>

    Database design

    The database contains a table called 'Users' and the fieldname is 'name'.

  12. Bala said 8 months later:

    Can you find the probs on above code

  13. wolfmanjm said 8 months later:

    The code in my article works fine, I use it. If you are having problems, then send me more information on what problems you are having, or send me your code. The email address is at the top of this page on the right.

  14. Curtis said 9 months later:

    What does your partial look like?

  15. Curtis said 9 months later:

    Maybe this?

      `<ul>`
        <% @names.each do|name|%>
        <li><%= name %></li>
        <%end%>
      `</ul>`
    
  16. wolfmanjm said 9 months later:

    The partial I usually use is somewhat more complex as I like to include the ID. However there is a default used which looks much like what you show above, and for the purposes of this article should be sufficient.

  17. julien said about 1 year later:

    Just wanted to say thanks for this! It solved my problem completely (I had the same issue with autogenerated fields) and it works like a charm. This should replace the standard textfieldwith_autocomplete for future releases of RoR

  18. Jared said about 1 year later:

    Just thought you know this has been fixed:

    http://dev.rubyonrails.org/attachment/ticket/5983/add_index_support_to_text_field_with_auto_complete.diff

Trackbacks

Use the following link to trackback from your own site:
http://blog.wolfman.com/articles/trackback/56

(leave url/email »)

   Comment Markup Help Preview comment