views:

53

answers:

2

I am totally new to javascript and am probably biting of more than I can chew, but I am trying to get the jQuery autcomplete widget working on my Rails site.

I have a page called "links" where I want to be able to assign a person to a link. Using the autocomplete I should be able to have a textbox that drops down a list of peoples names suggested by the autocomplete, and when selected, the persons name remains in the textbox. But when the form is submitted I don't want the persons name sent with the form, I want the persons ID sent with the form.

So the question is how to have the persons name once selected, remain in the textbox, but once submitted the persons id is submitted.

In Rails, this is how I am supplying the JSON data from my Person controller:

def index  
  if params[:term]
    @people = Person.find(:all,:conditions => ['given_name LIKE ?', "#{params[:term]}%"],  :limit => 5)
  else
    @people = Person.all
  end

  respond_to do |format|  
    format.html # index.html.erb  
    format.json { render :json => @people.to_json(:only => [:id, :given_name]) }
    end
end

The above outputs the following JSON text:

[{"person":{"id":1,"given_name":"dale"}},{"person":{"id":2,"given_name":"sally"}},{"person":{"id":3,"given_name":"joe"}}]

Using the jQuery autocomplete plugin, how do I have the 'given_name' appear in the suggested matches, leave the 'given_name' in the textbox once selected, but send the 'id' value when the form is submitted.

I think I need to specify in the javascript what to label to show and what value to send. As I am just getting the hang of javascript, if you could explain how your answer works that would be appreciated. Thanks.

+1  A: 

The best answer I can come up with is to create a hidden input field for the person's id. When you select a name, the result() function updates the value of the hidden input with the id:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
                    "http://www.w3.org/TR/html4/loose.dtd"&gt;
<html>
<head>
  <script src="http://code.jquery.com/jquery-latest.js"&gt;&lt;/script&gt;
  <link rel="stylesheet" href="http://dev.jquery.com/view/trunk/plugins/autocomplete/demo/main.css" type="text/css" />
  <link rel="stylesheet" href="http://dev.jquery.com/view/trunk/plugins/autocomplete/jquery.autocomplete.css" type="text/css" />
  <script type="text/javascript" src="http://dev.jquery.com/view/trunk/plugins/autocomplete/lib/jquery.bgiframe.min.js"&gt;&lt;/script&gt;
  <script type="text/javascript" src="http://dev.jquery.com/view/trunk/plugins/autocomplete/lib/jquery.dimensions.js"&gt;&lt;/script&gt;
  <script type="text/javascript" src="http://dev.jquery.com/view/trunk/plugins/autocomplete/jquery.autocomplete.js"&gt;&lt;/script&gt;
  <script>
  $(document).ready(function(){
    // your data
    var data = [{"person":{"id":1,"given_name":"dale"}},{"person":{"id":2,"given_name":"sally"}},{"person":{"id":3,"given_name":"joe"}}];


    $("#person_name").autocomplete(data, {
      // formatting of choices in drop down
      formatItem: function(item) {
        return item.person.given_name;
      },
      // format of choice in input field
      formatResult: function(item) {
        return item.person.given_name + " (" + item.person.id + ")";
      }

      // when choice is made, update value of hidden field with the id
    }).result(function(event, data, formatted) {
      $("#person_id").val(data.person.id);
    });
  });
  </script>

</head>
<body>
  Select a person: <input id="person_name" /> (dale, sally, joe)
  <input type="hidden" id="person_id"/>
</body>
</html>
Ken Earley
Thanks for your reply. I think your solution will work, but I was hoping that the ability to send a different value than the one shown in the textbox would be built into jQuery widget. It seems like this should be possible without the hidden field, but I am not grasping something. If it is not possible than I will roll with the hidden field solution.
Dale
I re-reviewed the jQuery widget docs and your answer is correct. The way to send a different value than the one shown in the textfield (as in a person's ID and not the persons name selected) is through a hidden field. I think I was making this too complicated by trying to make the widget supply the hidden value by itself. The example in the docs clearly shows that the widget is used in combination with a hidden field. Thanks.
Dale
+1  A: 

This is built into autocomplete. Look at some of the examples-- one of the ones returns data in this format:

[{
    "id": "Ciconia ciconia",
    "label": "White Stork",
    "value": "White Stork2"
},
{
    "id": "Platalea leucorodia",
    "label": "Spoonbill",
    "value": "Spoonbill"
}]

You can supply labels and values differently.

Matt
Thanks for the fast reply. What you have pointed out is what I am looking for, the built in feature. Do you have any pointers on how to implement this? I could be wrong but what I understood from the docs, is that "label" is what is shown in the dropdown list, and "value" is what gets stored in the textfield once a "label" is selected.The only thing I have managed to do is select the "label" such as "label": "Joe" which then stores the value '4' (the persons ID) in the text field. This is functional, but looks stupid as no one wants to actually see the persons ID. Any ideas on this?
Dale
Just re-reviewed the docs on the jQuery widget as you suggested, and I think I have figured this out now between your answer and @ken's answer below. Per the docs I can specify different values as above, and then feed a value to a hidden field, which will then be sent to my Rails app.I guess I was making this too complicated as I was trying to somehow make the jQuery widget supply the hidden value, when the example in the docs clearly show that the widget is used in combination with a hidden field. Thanks.
Dale
(I tried to mark both your answer and @Ken's answer as correct but it only lets pick one! Your answer pointed me to the correct doc, but @Ken's original answer was the solution per the docs.)
Dale
@Dale - If you want, you can give Matt an upvote. That will at least give him some points.
Ken Earley
@Ken - I am new to stack overflow so don't even have enough rep points to be able to upvote yet! ( I need at least 15).
Dale