bootstrap typeahead return name and id
Asked Answered
L

6

8

Hy! I'm using twitter bootstraps typeahead:

I'm calling a page that returns a response with json_encode the page returns a name and an ID,

I want that the typeahead list will show me the list of names, and when I select one of the name to write the id value to a hidden field.

the calling works fine, and to write a field should be easy. what i dont know what to do is how to divide the name from the id.

now, when i search something, in the suggesstion list I can see the returning results like this:

name1:id1 name2:id2

i only want to see names but to carry the value of id too.

how can i do that?

 $(function(){
    $("#typeahead_<? print $key; ?>").typeahead(
        {
        source: function(query, process)
                    {
                    $.ajax({
                        url:    '/getAjaxProducts',
                        type:   'POST',
                        data:   'query=' + query,
                        dataType: 'JSON',
                        async: true,
                        success: function(data)
                                {
                                process(data);
                                }
                            });                 
                    }
        });
});
Luncheon answered 3/1, 2013 at 10:25 Comment(0)
M
21

A typical JSON document that contains name/ID pairs is going to look like this:

[
  {
    "id": 1
    "name": "firstName"
  },
  {
    "id": 2
    "name": "secondName"
  }
]

The strategy here is to build an object literal that maps names to IDs as you parse the result, while only using the name to populate the typeahead:

var productNames = new Array();
var productIds = new Object();
$.getJSON( '/getAjaxProducts', null,
        function ( jsonData )
        {
            $.each( jsonData, function ( index, product )
            {
                productNames.push( product.name );
                productIds[product.name] = product.id;
            } );
            $( '#product' ).typeahead( { source:productNames } );
        } );

Once the user selects an item from the typeahead, you can reference the selected item with:

$( '#product' ).val()

and you can get the ID associated with the selected item with:

productIds[$( '#product' ).val()]

From your question, it looks like your JSON document may be structured a little bit differently, so you would change the parsing as appropriate, but the same general strategy applies.

Moffitt answered 4/1, 2013 at 22:51 Comment(5)
This solution implies that the names are unique. In most cases they probably are, but I felt that I needed to point that out.Abomasum
With the latest typeahead.js it's local:productNames rather than source:productNames.Alanna
I can't imagine what the use-case would be for a situation where the names are not unique. This means you would have two identical options in the dropdown, with no means for the end-user to differentiate between them. How would the user know what to select?Moffitt
The use case would be a situation where you have people's names, like John James and Bill Johnson. You could differentiate for the user by rendering custom templates with profile pictures (so, your JSON might need to have fields for id, name, and profile pic URL).Dunagan
This solution loaded all the data at once right? As I don't see the query parameter. There would be an issue if the backend only return certain amount of data. I.E. you have to assign query parameter for more specific data.Unbuckle
S
11

Sorry to "resurect" this post but i was going to be crazy !

If some of you have problems using theses sample codes ( none of them were working, all were returning "Undefined" instead of showing the name

Just add

displayKey: 'name',

Replace of course 'name' by your label var name returned by your remote source

( Quite hard to find up to date samples on it, most of samples found on the net are for the previous version of typeahead and not compatibles with new ones ... )

Schaal answered 16/6, 2014 at 11:1 Comment(1)
This is the correct approach. Any solution that relies on the displayed string will break easily.Glottal
P
9
......updater: function (item) {
        var item = JSON.parse(item);
        console.log(item.name); 
        $('#VehicleAssignedTechId').val(item.id);       
        return item.name;
    }

On updater of the typeahead call you can put as above code which allows you to add selcted value in the textbox or where you have to put its value in other hidden field.

Full ajax call is as below:

$('#VehicleAssignedTechName').typeahead({
    source: function(query, process) {
        var $url =SITE_URL+ 'api/vehicle_techfield_typeahead/' + query + '.json';
        var $items = new Array;
        $items = [""];
        $.ajax({
            url: $url,
            dataType: "json",
            type: "POST",
            success: function(data) {
                console.log(data);
                $.map(data, function(data){
                    var group;
                    group = {
                        id: data.id,
                        name: data.name,                            
                        toString: function () {
                            return JSON.stringify(this);
                            //return this.app;
                        },
                        toLowerCase: function () {
                            return this.name.toLowerCase();
                        },
                        indexOf: function (string) {
                            return String.prototype.indexOf.apply(this.name, arguments);
                        },
                        replace: function (string) {
                            var value = '';
                            value +=  this.name;
                            if(typeof(this.level) != 'undefined') {
                                value += ' <span class="pull-right muted">';
                                value += this.level;
                                value += '</span>';
                            }
                            return String.prototype.replace.apply('<div style="padding: 10px; font-size: 1.5em;">' + value + '</div>', arguments);
                        }
                    };
                    $items.push(group);
                });

                process($items);
            }
        });
    },
    property: 'name',
    items: 10,
    minLength: 2,
    updater: function (item) {
        var item = JSON.parse(item);
        console.log(item.name); 
        $('#VehicleAssignedTechId').val(item.id);       
        return item.name;
    }
});
Pentachlorophenol answered 26/2, 2013 at 6:4 Comment(1)
useful, thanks. Just also need add substr method. substr: function(string) { return String.prototype.substr.apply(this.name, arguments); }Disannul
M
1

My solution is:

var productNames = new Array();
var productIds = new Object();
$.getJSON( '/getAjaxProducts', null,
        function ( jsonData )
        {
            $.each( jsonData, function ( index, product )
            {
                productNames.push( product.id + product.name );
                productIds[product.id + product.name] = product.id;
            } );
            $( '#product' ).typeahead( { source:productNames } );
        } );

In my case, product.id is a code, so it is useful to display it in typeahead control. In this way i avoided duplicated names risk.

Monotint answered 23/2, 2017 at 9:13 Comment(0)
M
0

I noticed when using this code that if the match included the letters 'st', the typeahead suggestions include the style tag in the typeahead suggestions.

For example the suggested matches would show

style="padding: 10px; font-size: 1.5em;">standard

instead of

standard

I changed the replace function to this:

replace: function (string) {
  return String.prototype.replace.apply(this.name, arguments);
}

Obviously you lose the additional formatting, but it doesn't break on 'st' matches (I assume it would also break on 'di', or other substrings of the div tag.

Mannerly answered 16/5, 2013 at 17:35 Comment(0)
B
0

I had the same issue when i tried to process username and id.I had a tricky fix but later on i have fixed it with proper solution.

Have a look at this one,

$('#search').typeahead({
 source: function(query, process) {
 var $url = "/controller/function/list_users/?q="+query;
 var $datas = new Array;
 $datas = [""];
 $.ajax({
 url: $url,
 dataType: "json",
 type: "GET",
 success: function(data) {
 $.map(data, function(data){
 var group;
 group = {
 id: data.id,
 name: data.user_name,
 toString: function () {
 return JSON.stringify(this);
 //return this.variable;
 },
 toLowerCase: function () {
 return this.name.toLowerCase();
 },
 indexOf: function (string) {
 return String.prototype.indexOf.apply(this.name, arguments);
 },
 replace: function (string) {
 var value = '';
 value += this.name;
 if(typeof(this.name) != 'undefined') {
 value += ' <span class="pull-right muted">';
 //value += this.name;
 value += '</span>';
 }
 return String.prototype.replace.apply('<div style="padding: 10px; font-size: 1em;">' + value + '</div>', arguments);
 }
 };
 $datas.push(group);
 });
process($datas);
 }
 });
 },
 property: 'user_name',
 items: 10,
 minLength: 2,
 updater: function (item) {
 var item = JSON.parse(item);
 $('#hiddenId').val(item.id);
 $('#username').val(item.name);
//you can perform your actions here
//example</p>
//location = '/controller/function/'+item.id+'/edit';
 //document.redirect = location;
}
});

look at this link also.

http://vaisakhvm.wordpress.com/2013/07/31/twitter-bootstrap-typeahead-process-multiple-values/

Blais answered 31/7, 2013 at 6:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.