views:

1393

answers:

2

I want to have a text box that the user can type in that shows an Ajax-populated list of my model's names, and then when the user selects one I want the HTML to save the model's ID, and use that when the form is submitted.

I've been poking at the auto_complete plugin that got excised in Rails 2, but it seems to have no inkling that this might be useful. There's a Railscast episode that covers using that plugin, but it doesn't touch on this topic. The comments point out that it could be an issue, and point to model_auto_completer as a possible solution, which seems to work if the viewed items are simple strings, but the inserted text includes lots of junk spaces if (as I would like to do) you include a picture into the list items, despite what the documentation says.

I could probably hack model_auto_completer into shape, and I may still end up doing so, but I am eager to find out if there are better options out there.

+1  A: 

I rolled my own. The process is a little convoluted, but...

I just made a text_field on the form with an observer. When you start typing into the text field, the observer sends the search string and the controller returns a list of objects (maximum of 10).

The objects are then sent to render via a partial which fills out the dynamic autocomplete search results. The partial actually populates link_to_remote lines that post back to the controller again. The link_to_remote sends the id of the user selection and then some RJS cleans up the search, fills in the name in the text field, and then places the selected id into a hidden form field.

Phew... I couldn't find a plugin to do this at the time, so I rolled my own, I hope all that makes sense.

Dan Harper - Leopard CRM
A: 

I've got a hackneyed fix for the junk spaces from the image. I added a :after_update_element => "trimSelectedItem" to the options hash of the model_auto_completer (that's the first hash of the three given). My trimSelectedItem then finds the appropriate sub-element and uses the contents of that for the element value:

function trimSelectedItem(element, value, hiddenField, modelID) {
 var span = value.down('span.display-text')
 console.log(span)
 var text = span.innerText || span.textContent
 console.log(text)
 element.value = text
}

However, this then runs afoul of the :allow_free_text option, which by default changes the text back as soon as the text box loses focus if the text inside is not a "valid" item from the list. So I had to turn that off, too, by passing :allow_free_text => true into the options hash (again, the first hash). I'd really rather it remained on, though.

So my current call to create the autocompleter is:

<%= model_auto_completer(
    "line_items_info[][name]", "", 
    "line_items_info[][id]", "",
    {:url => formatted_products_path(:js),
     :after_update_element => "trimSelectedItem",
     :allow_free_text => true},
    {:class => 'product-selector'},
    {:method => 'GET',  :param_name => 'q'}) %>

And the products/index.js.erb is:

 <ul class='products'>
    <%- for product in @products -%>
    <li id="<%= dom_id(product) %>">
            <%= image_tag image_product_path(product), :alt => "" %>
            <span class='display-text'><%=h product.name %></span>
    </li>
    <%- end -%>
 </ul>
TALlama