Twitter’s Bootstrap is all the rage these days, and for good reason. It’s chock full of aesthetically pleasing, easily customizable styles and useful widgets. Among the latter you’ll find typeahead, a widget for auto-suggesting possible values in response to user input.

Typeahead Using an Array of Strings

Bootstrap’s standard implementation of typeahead uses an array of strings to provide suggestions:

html:

<body>
<input id="search"/>
</body>

JavaScript:

var colors = ["red", "blue", "green", "yellow", "brown", "black"];

$('#search').typeahead({source: colors});

Here’s what the widget looks like:

The implementation is simple, clean, and works as expected. What more could you want?

Typeahead Using an Array of Objects

Well, sometimes working with strings is too limiting. For example, consider a scenario where you want the user to enter a US state and you need to capture the two-letter state abbreviation once the selection is made (if the user enters “California”, you’ll store “CA”):

To build this feature we could use an array of objects which contain both the name of the state and the abbreviation:

var stateList = [
{"stateCode": "CA", "stateName": "California"},
{"stateCode": "AZ", "stateName": "Arizona"},
{"stateCode": "NY", "stateName": "New York"},
{"stateCode": "NV", "stateName": "Nevada"},
{"stateCode": "OH", "stateName": "Ohio"},
...
];

Bootstrap exposes a set of overridable options we can leverage to implement typeahead with an array of objects:

  1. Source
  2. Matcher
  3. Sorter
  4. Highlighter
  5. Updater

It’s important to note that you can probably leverage Bootstrap’s own implementations for pretty much everything except source and updater. That said, in this example, we will implement all of them using the template below:

$('#search').typeahead({
source: function (query, process) {
// implementation
},
updater: function (item) {
// implementation
},
matcher: function (item) {
// implementation
},
sorter: function (items) {
// implementation
},
highlighter: function (item) {
// implementation
},
});

1. Source

Let’s begin with source. This option specifies the data set to use for the auto-suggest list. It can take either an array of strings (which we saw in the first example) or a function:

source: function (query, process) {
states = [];
map = {};

var data = [
{"stateCode": "CA", "stateName": "California"},
{"stateCode": "AZ", "stateName": "Arizona"},
{"stateCode": "NY", "stateName": "New York"},
{"stateCode": "NV", "stateName": "Nevada"},
{"stateCode": "OH", "stateName": "Ohio"}
];

$.each(data, function (i, state) {
map[state.stateName] = state;
states.push(state.stateName);
});

process(states);
},

This function takes two parameters: query and process (I’ll talk about both in a bit). The first thing we do is get data, an array of state objects. Though I’ve hardcoded contents of data inside the function in this example, in a real production app it would come from the server.

Next, we map state names to the corresponding objects using two global variables, map and states. This is necessary because Bootstrap needs a list of strings to actually display auto suggestions (states array), while we need to get the original objects (stored in the map). Obviously, names of your objects need to be unique for this to work.

Finally, we call Bootstrap’s process() function with the states array. Process() orchestrates the event loop for typeahead (by calling matcher, sorter, etc) and sets up the auto-suggest list displayed to the user.

You may have also noticed that we didn’t use query input parameter in this example. Typically, query would be used to implement server-side filtering of the auto-suggestion list because it contains the search string entered by the user.

2. Matcher

Next, let’s implement the matcher(). This function is used by Bootstrap to check if the search string typed by the user matches anything in the source list. Its purpose is to filter the auto-suggest list to only the relevant values:

matcher: function (item) {
if (item.toLowerCase().indexOf(this.query.trim().toLowerCase()) != -1) {
return true;
}
}

The implementation above is fairly trivial. We simply take user’s input (contained in this.query) and check to see if it exists anywhere in the item. Conversion of both strings to lower case is needed because the user is unlikely to expect case to be considered when matching terms.

3. Sorter

The Sorter function is responsible for sorting the list of suggestions filtered by the matcher:

sorter: function (items) {
return items.sort();
}

Again, I should note that my implementation is quite simplistic. Sorting suggestions is usually a more elaborate affair. For example, Bootstrap’s own implementation considers whether user input is found at the beginning of the suggested string and whether the match was case sensitive.

4. Highlighter

Bootstrap uses highlighter to highlight user’s input within auto-suggested results. We can use a simple regex match to find and bold user’s input:

highlighter: function (item) {
var regex = new RegExp( '(' + this.query + ')', 'gi' );
return item.replace( regex, "<strong>$1</strong>" );
}

5. Updater

Finally, we get to the updater. This function is called by Bootstrap once the user selects an item, which gives us a chance to do something with the selection. In this case, we’d like to record the selected state abbreviation in a global variable selectedState before returning the item:

updater: function (item) {
selectedState = map[item].stateCode;
return item;
}

Note of caution: it’s very important that you return the item because that’s the value used by Bootstrap to set the input box.

References:

https://github.com/twitter/bootstrap/pull/3682

http://twitter.github.com/bootstrap/javascript.html#typeahead

You may also like:

Did you love / hate / were unmoved by this post?
Then show your support / disgust / indifference by following me on Twitter!

This post got 86 comments so far. Care to add yours?

  1. Gerbus says:

    Not sure where the variable ‘mapped’ comes from in the update event.

  2. biesior says:

    Alex, apparently you didn’t fix the mapped[item] in your code, anyway after fixing it’s working like a charm, thanks a lot to both of you! (Alex & Gerbus)

  3. Alex Tatiyants says:

    Hi Biesior, I did actually fix the updater() to use stateCode:

    updater: function (item) {
    selectedState = mapped[item].stateCode;
    return item;
    }

    Are you seeing something different? Anyway, thanks for your comment, glad you found the tutorial useful.

  4. Vincent says:

    Yes! Yes! Thanks a lot… I’ve not tested yet but I think, I hope that is the missed piece of my puzzle. I gonna test it now…

  5. Jake says:

    Also, the variable for map needs to be declared outside of your process function (globally) so that it can later be referenced in the updater function, unless I am missing something. This was the only way I could get it to work. Thanks for the tutorial though! Great job.

  6. Pachocho says:

    Hi Alex,
    Is there a way to make it work without the item’s labels being unique?

    If the typeahead is used to find people then unique names are not secure…

    Thank you!

    • Alex Tatiyants says:

      Hi Pachocho, I’m not sure how you’d do this since you need some way to unambiguously identify a value in the map. Sorry.

      • Steve Cooper says:

        I’ve found an approach for this, and written it up here: http://stevedrivendevelopment.com/2013/02/10/using-twitter-bootstrap-typeahead-to-select-a-keyvalue-pair-not-a-string/

        it uses the ‘highlighter’ function and a little bit of JSON. Highlighter is a bit of a misnomer — it’s actually an arbitrary function for re-writing the text that appears in the dropdown.

        Set the source option to a function returning an array of JSON-serialized name/value pairs;

        return [
        JSON.stringify({ name:”mylabel”, value: 4 }}
        ];

        Set the highlighter to return just the name, not the value;

        highlighter: function(item) {
        return JSON.parse(item).name;
        }

        Set the matcher to return things that match the right name;

        matcher: function (item) {
        return JSON.parse(item).name.toLocaleLowerCase().indexOf(this.query.toLocaleLowerCase()) != -1;
        }

        Use the updater to catch the selected item;

        updater: function (item) {
        alert(JSON.parse(item).value);
        return JSON.parse(item).name;
        }

        This pattern lets you search for text but return a corresponding key.

  7. Ryano says:

    Thanks heaps for this. Just what i was looking for.
    I wish all the bootstrap plugins had formal documentation and examples for each option, so i don’t need to google everything. 🙂

  8. Amir says:

    Just what I need; that one important thing that’s missing for bootstrap newbies such as myself: examples. 🙂

    PS:
    Needs to change “mapped” to “map” in the updater function; and voila!

  9. Ankur says:

    Very helpful post..Found this after a lot of struggling through other links. Wish I could have found this earlier.
    They should make something like this part of the official documentation.

  10. GroovyBoy says:

    You’re storing a map and an array of the source data in there with the same data. Basically, you’re increasing the memory load on the browser!

    • Alex Tatiyants says:

      You’re right GroovyBoy, I am increasing the load. That said, if you have a way that doesn’t increase the load, I’m all ears. thanks

  11. Ronald says:

    Thanks a lot for your post, it did helped get implemented typeahead into my app.

    • Alex Tatiyants says:

      You’re welcome Ronald, glad it was helpful!

    • Mark S says:

      Helpful article thank you. Do you know if there is a way to prevent typeahead from updating the field with the selected value?

  12. Onur says:

    Ty for posting.

    I have a user JsonGet User Source;

    (Just Display Name)

    But i need autocomplate(typehead) clicked: windowlocation.href=xxx.com/xxx/?user=source_id

    Note: I have Loop in Dislay Name and id, but i dont know this array values and recidet fonksiyon. Thx

    • Onur says:

      Thx, my ask end from Updater 😉 ty Alex very nice.

    • Alex Tatiyants says:

      Hi Onur, I’m having a bit of difficulty understanding your question. Are you saying that you have a JSON object user, which contains a property called source and you’d like to use it to construct and redirect to a url?

      If that’s the case, you’d probably want to do something like this in the updater():

      updater: function (item) {
          window.location = "xxx.com/xxx/?user=" + map[item].source_id;
      }
      

      Hope this helps, thanks

  13. Scott says:

    Hi Alex,

    I’ve followed your code above and altered it to pull from my Database, I’m getting an odd issue though, If I type fast enough into the text box I will sometimes get double results, Do you know why this might be? I assume it’s something to do with the global state and map variables though I’m not sure

    Cheers

    Scott

    • Scott says:

      By changing the state variable in the source function to var state = [] I seem to have fixed my own issue, but I’m not sure if this will effect other things later on, I’ll guess I’ll play around some more and see! Thanks

      • germanger says:

        Thanks for that!, it worked for me.
        Although I find it weird that nobody else is experiencing this problem (problem: typing fast gives repeated results)

      • Thiago says:

        Hi Scott,

        I’m having double results as well but you solution didn’t work for me. Where exactly you set the variable to []?
        I’m on things for too long already, I’m starting to consider using another solution…

  14. H-Works says:

    Absolutely great article, thank you so much.

    Its very rare to find such precise, clear and illustrated documentation online.

  15. I would like to add to excellent article, cascading multiple typeahead fields:
    Assume you have a subject,course, and code.
    – Subjects populates in itself
    – Course populates with the Subject’s selection
    – Section populates with the Course and Subject’s selection

    Notice we need the code and not the name from each json array of the form [ {code: value, name: value}……]

    Assume you have three fields and want to cascade them using type ahead, here is an elegant solution, by reusing your code. In this case all the data comes from server.

    The only thing deserves an explanation is this code in the updater :
    var name_box = $(‘#class-details-subject’).val();
    var name_data = $(‘#class-details-subject’).data(‘name’);
    if ( name_box != name_data ) {
    $(‘#class-details-subject’).data(‘code’, name_box);
    }

    This piece makes sure we obtain the most recent data in the input fields. Hope it helps

    $(‘#class-details-subject’).typeahead({
    source: function (query, process) {
    // implementation
    return $.getJSON(
    ‘/subjects_like’ ,
    { query: query },
    function (data) {
    subjects = [];
    map = {};
    $.each(data, function (i, subject) {
    map[subject.name] = subject;
    subjects.push(subject.name);
    });
    process(subjects);
    });
    },
    updater: function (item) {
    // implementation
    $(‘#class-details-subject’).data(‘code’, map[item].code);
    $(‘#class-details-subject’).data(‘name’, map[item].name);
    return item;
    },
    matcher: function (item) {
    // implementation
    if (item.toLowerCase().indexOf(this.query.trim().toLowerCase()) != -1) {
    return true;
    }
    },
    sorter: function (items) {
    // implementation
    return items.sort();
    },
    highlighter: function (item) {
    // implementation
    var regex = new RegExp( ‘(‘ + this.query + ‘)’, ‘gi’ );
    return item.replace( regex, “$1” );
    },
    });

    $(‘#class-details-course’).typeahead({
    source: function (query, process) {
    var name_box = $(‘#class-details-subject’).val();
    var name_data = $(‘#class-details-subject’).data(‘name’);
    if ( name_box != name_data ) {
    $(‘#class-details-subject’).data(‘code’, name_box);
    }
    var subject = $(‘#class-details-subject’).data(‘code’);

    return $.getJSON(
    ‘/courses_like?subject=’ + subject,
    { query: query },
    function (data) {
    return process(data);
    });
    }
    });

    $(‘#class-details-section’).typeahead({
    source: function (query, process) {
    var name_box = $(‘#class-details-subject’).val();
    var name_data = $(‘#class-details-subject’).data(‘name’);
    if ( name_box != name_data ) {
    $(‘#class-details-subject’).data(‘code’, name_box);
    }

    var subject = $(‘#class-details-subject’).data(‘code’);
    var course = $(‘#class-details-course’).val();
    return $.getJSON(
    ‘/sections_like?subject=’ + subject + ‘&course=’ + course ,
    { query: query },
    function (data) {
    return process(data);
    });
    }
    })

    Hope it helps

    Eric Echeverri

  16. Anusha Anand says:

    A well documented write up. If i had come across it a day before i would have saved lot of time. Thanks Alex you saved my day..

    I have another problem in FF where, if i press keydown it traverse alternate data only. i.e, next and prev is not working accordingly. It is bootstrap typeahead bug. Any thoughts on this.

    • Alex Tatiyants says:

      Hi Anusha, glad you found it useful. As for the bug you mention, I haven’t seen it myself though I don’t use Firefox on a regular basis. Sorry.

  17. brilliantly simple! I created a more complex “map” object and I am now able to set the value of a hidden field and update a photo one the code hits the “updater” function. I also hijack the form’s submit event to check that the value of the textbox and the hidden field are valid. I prevent the submission of the form whenever those fields do not match any of the allowed values. Pretty sweet really.

    One thing to note guys, is that the source function runs every time the value of textbox changes. This being said, if you have no need to run ajax to look-up new data, it would be best to move the algorithm for building the states array and map object to outside the typeahead source function.

    • Alex Tatiyants says:

      Hi Angel, yes, there’s a lot of cool stuff you can do with this technique. Thank you very much for sharing!

  18. Gus says:

    Hello,

    There is one thing missing, I scroll the comment, but didn’t see anything about that… What happen if the user clear it out the field?? The updater only update de hidden field when there is a match but in my case of use since there is no zero entry in value there is no match so the hidden field value stays to the last match label entry in the field… I know it pretty dumb to not complete a form, but you know with users you never know!!

    Gus

    • Nadjib Bait says:

      Yes you’re right. I have the same issue. Did you manage to get it work? I think of reseting the value of the hidden input each time the user changes the Typeahead box (delete or add a letter) but I don’t know if it’s too much… and also the Change event must happens before the Updater function of the Typeahead…

    • Steve Downey says:

      I handled this with a keyup handler:

      $(‘#search’).keyup(function() {
      selectedState = ”;
      });

  19. Rahul Patil says:

    Hello Alex..

    Amazing article this is. Helping me a lot with typeahead functionality that I am using in my project.

    I have some doubts. I want to append selected JSON object to html attribute. I tried doing it in updater function but it does not work.

    Here is the scenario. Patient information is stored in JSON. I use typeahead to search patient name. When I select patient name, it will show Patient name, age, etc information in with some id..

    Any way to achieve this?

    • Alex Tatiyants says:

      Hi Rahul,

      Thanks for reading, glad you found it useful. To answer your question, there are many ways to bind JSON data to HTML. Probably the easiest is using jQuery.

      Suppose you have the following HTML to display patient data:

      <div>
         <span>patient id</span>
         <span id="patient-id"></span>
         
         <span>patient name</span>
         <span id="patient-name"></span>
         
         <!-- more patient fields --!>
      </div>
      

      Also suppose that the JSON representing patient data stored in your map[] looks like this:

      {"patient": 
         {
         "patientId": "123",
         "patientName": "John Smith"
         // more fields
         }
      }
      

      Now, once the patient is selected, you can do the following in the updater():

      updater: function (item) {
          val patient = map[item];
          $('#patient-id').val(patient.patientId);
          $('#patient-name').val(patient.patientName);
          // set more fields
          return item;
      }
      

      Hope this helps.

      • Rahul Patil says:

        Thank you so so much for a prompt help. Much much much appreciated. Glad I read blogs of people like you. Added your blog to my feed.. 🙂

        I forgot to return item; that was the problem I guess.

        Keep in touch,

        Regards,
        Rahul P
        (Wrapcode.com)

        • chirag dhori says:

          hi rahul i have same problem .. but i new to yii and json. from array i got value and while from data base i dnt know how to get it.. if some documentation available pleas share this.

          regards,
          chirag

  20. Alex says:

    I copy and paste and it didn’t work =(

    $(‘input.autocomplete’).typeahead({
    source: function (query, process) {
    states = [];
    map = {};

    var data = [
    {“stateCode”: “CA”, “stateName”: “California”},
    {“stateCode”: “AZ”, “stateName”: “Arizona”},
    {“stateCode”: “NY”, “stateName”: “New York”},
    {“stateCode”: “NV”, “stateName”: “Nevada”},
    {“stateCode”: “OH”, “stateName”: “Ohio”}
    ];

    $.each(data, function (i, state) {
    map[state.stateName] = state;
    states.push(state.stateName);
    });
    process(states);
    },
    matcher: function (item) {
    if (item.toLowerCase().indexOf(this.query.trim().toLowerCase()) != -1) {
    return true;
    },
    sorter: function (items) {
    return items.sort();
    },
    highlighter: function (item) {
    var regex = new RegExp( ‘(‘ + this.query + ‘)’, ‘gi’ );
    return item.replace( regex, “$1” );
    },
    updater: function (item) {
    selectedState = map[item].stateCode;
    return item;
    }
    });

    • Alex Tatiyants says:

      Sorry to hear that Alex, what’s the specific error you’re getting?

      • Alex says:

        In the matcher

        item is undefined
        if (item.toLowerCase().indexOf(this.query.trim().toLowerCase()) != -1) {

  21. Alex says:

    Ok This is my problem

    $(‘:input.autocomplete’).typeahead({
    minLength: 3,
    source: function(query, process) {
    objects = [];
    map = {};
    var data = [{“id”:803,”label”:”Imaginaria Sac”},{“id”:804,”label”:”One Sac”},{“id”:805,”label”:”All Feliz Sac”}];
    $.each(data, function(i, object) {
    map[object.label] = object;
    objects.push(object.label);
    });
    process(objects);
    },
    updater: function(item) {
    $(‘#idclien’).val(map[item].id);
    return item;
    }
    });

    I understand this, but it doesn’t work. I only want save the ID in the hidden field

    The error is:
    Item is undefined
    return ~item.toLowerCase().indexOf(this.query.toLowerCase())
    bootstrap.js (línea 1652)

    Thanks

  22. Alexander says:

    Awesome tutorial. Really good job

  23. John says:

    Alex,

    I’m trying to create a search bar for my own website. The goal is to have the typeahead provide choices and when the user selects a choice, it takes them to a new page. At the moment the typeahead works and I get redirected but using Firebird it says it is undefined. I’m wanted to save the url address with the search query words, but I’m not sure if this is right.

    $(function(){

    var map = {};
    var pages = [];

    $(“.typeahead”).typeahead({
    source: function ( query, process ) {
    $.ajax({
    url: ‘json/ortho.json’
    ,prefetch: ‘json/ortho.json’
    ,cache: false
    ,success: function(data){

    map = {};
    pages = [];

    _.each( data, function(item, ix, list){
    pages.push( item.name );
    map[ item.name ] = item.id;
    });
    process( pages );
    }
    });
    }

    ,matcher: function (item) {
    if (item.toLowerCase().indexOf(this.query.trim().toLowerCase()) != -1) {
    return true;
    }
    }

    ,sorter: function (items) {
    return items.sort();
    }

    ,highlighter: function (item) {
    var regex = new RegExp( ‘(‘ + this.query + ‘)’, ‘gi’ );
    return item.replace( regex, “$1” );
    }
    ,updater: function ( selectedName ) {

    $( “#websitehref” ).val( map[ selectedName ] );
    return window.location.href = $(selectedName).attr(“id”);

    }
    });
    });

    And the JSON file

    [
    { “id”:”#index.html”, “name”:”invisalign” }
    ,{ “id”:2, “name”:”braces” }
    ,{ “id”:3, “name”:”seperators” }
    ,{ “id”:4, “name”:”spacers” }
    ,{ “id”:5, “name”:”brushing” }
    ,{ “id”:6, “name”:”nance” }
    ,{ “id”:7, “name”:”fees” }
    ,{ “id”:8, “name”:”retainers” }
    ]

    I used some of your code and Adam’s code from fusiongrokker.com. I hope you can help me get a better idea on this thanks…

    John

  24. Neil Thompson says:

    Great Article – Thank you.

  25. altsys says:

    Thanks for the tutorial its really nice but I can’t figure out this error. can anyone help. I have tried the suggestion by Cinthia Davalos

    Uncaught TypeError: Cannot call method ‘toLowerCase’ of undefined

  26. Aidan says:

    Thanks a lot. Was helpful

  27. Mark S says:

    Helpful article thank you. Do you know if there is a way to prevent typeahead from updating the field with the selected value?

  28. […] Objetos jSON en Typeahead (Autocomplete) de Twitter Bootstrap […]

  29. Román says:

    Do you know if is there a present callback for mouse over the li?

  30. Dhiraj says:

    Nice Explaination…But I have one query..
    How we can force user to select value from typeahead result list only..and not allowing him to write any other value?

    • Alex Tatiyants says:

      Thanks Dhiraj. To answer your question, you control what the user selects in the updater(). In fact, the implementation in this example is essentially restricting the user to select a value from the result list because map[item] will be null for anything not in the list.

      You can be more extreme and not return a valid value from updater() unless it’s in the list, but that would make for a very awkward user experience.

      • Hunter says:

        In my case, I’m using Knockout.js for data binding, so my view-model already has a collection of the objects that was created in your code as a global (the ‘map’ variable). So instead of creating a fresh copy, I’m just referring to that mapping. As another commenter noted, the source function is called on every change to the textbox, so this is a bit faster to execute, not that it matters a whole lot on fast computers and non-IE 8 web browsers.

        Also, since the collection of objects is built externally, my source method is just:

        var items = thisCollectionIHave.map(function (item) {
        return item.name;
        });
        process(items);

        which uses the jQuery map() function to pretty simply pull the one member from the object. I’m pretty new to Knockout and to Bootstrap, so I’m feeling pretty proud of myself at the moment.

        Regarding callbacks (e.g., the parameter to the $.each() call in source()), I too hated the anonymous aspect of callbacks and always referred to my callback functions by name, defined elsewhere. But in an application of any substantial size, it just gets stupid trying to manage 100 two line callbacks, so I eventually just got over it. So I think “get over it” is a perfectly reasonable response. Life’s too short, right?

  31. leonel says:

    exelente!!!!

  32. Carlos says:

    Great!

    With your code I can fix duplicate itens…

    source: function(query, process){

    data = {}; // always clean before process.

    //…

    return process(data);

    }

  33. Mathieu Maes says:

    I don’t really like the fact that you’re using globals (map, states) in your example. It’s not just a matter of good practice, but you can actually get a lot of headaches if the page contains several typeahead controls.

    Also, this approach forces you to use an anonymous function inside the “source” function, because you need to create a callback function for the Ajax call which in turn needs to call the typeahead callback function (called “process” in your example). I tend to avoid using anonymous functions for readability and clarity purposes.

    So, this isn’t the solution I’m looking for yet… I know it’s easy to post criticism without an actual solution, so I will continue getting this to work myself and post an update soon! 🙂

    • Alex Tatiyants says:

      Hi Mathieu,

      Thanks for the comment, I appreciate it.

      As far as using globals, your point is well taken. There are of course techniques to limit leakage, but there’s only so much you can do with JavaScript (it loves its globals).

      As for using anonymous functions, I agree with the larger point, but not sure I fully understand the specific complaint here. The code inside source() is not anonymous and process() is being passed in by Bootstrap (so there’s not much you can do about it).

      Either way, I’d love to see what you’ve come up with,

      Thanks

  34. Thomas says:

    Just two words mate, “THANK YOU”

  35. Tony K says:

    Great post but for the life of me cannot get this to work correctly.

    I have my JSON data returning as this:
    {“COLUMNS”:[“USERNAME”,”ID”],”DATA”:[[“jclark”,”001650472″],[“jclark1″,”000086949”],[“jclarke”,”002386440″]]}

    My type-ahead code is as follows:

    $(function(){

    var map = {};
    var pages = [];

    $(‘#add_user’).typeahead({
    minLength: 3,
    source: function ( query, process ) {
    $.ajax({
    url: ‘/glv/_includes/gl_data.cfc?method=search_accounts_by_username&returnformat=json’
    ,prefetch: ‘/glv/_includes/gl_data.cfc?method=search_accounts_by_username&returnformat=json’
    ,cache: false
    ,success: function(data){

    map = {};
    pages = [];

    _.each( data, function(item, ix, list){
    pages.push( item.username );
    map[ item.username ] = item.id;
    });
    process( pages );
    }
    });
    }

    ,matcher: function (item) {
    if (item.toLowerCase().indexOf(this.query.trim().toLowerCase()) != -1) {
    return true;
    }
    }

    ,sorter: function (items) {
    return items.sort();
    }

    ,highlighter: function (item) {
    var regex = new RegExp( ‘(‘ + this.query + ‘)’, ‘gi’ );
    return item.replace( regex, “$1” );
    }
    ,updater: function ( selectedUsername ) {

    $(‘#add_user’).val( map[ selectedUsername ] );
    return window.location.href = $(selectedUsername).attr(“username”);

    }
    });
    });

    My input is never updated with matching accounts. What am I missing?
    I’ve spent 2 + days on this, any HELP is appreciated.

    THANK YOU

  36. mel says:

    Thanks for your post, it helps 🙂

  37. Marc B says:

    Thanks for writing this up. Definitely helped!

  38. kido says:

    How to bootstrap typehead from Mysql?

  39. alyx says:

    Thank you so much for this simple yet very complete explanation. It was really usefull!

  40. Ravi Kant says:

    please tell me how i create a autosuggest textbox value reterive from database with the help of json please tell me

  41. chirag dhori says:

    hi while working with array is working with absolutely fine in my yii applicaiton but while want to use with database its not working and since a week im finding code for how to get work with typeahead with yii.suggest me if any idea or related topic you have.

  42. Bhushan says:

    thanks this is really awesome

  43. Bass Jobsen says:

    With Twitter Bootstrap 3 the typeahead plugin had been dropped, but you can still use Bootstrap 3 Typeahead (https://github.com/bassjobsen/Bootstrap-3-Typeahead/)

  44. Punit Dave says:

    I Got Data[0] is undefined error , i am using same example , please suggest me if any thing is missing

  45. Cédric says:

    @Dave : you are probably using this typeahead : https://github.com/twitter/typeahead.js
    Replace [ states.push(state.stateName); ] by [ states.push({ value:state.stateName }); ]
    I hope this will help…

    Cédric

  46. sathio says:

    is it possible to use this method with bloodhound.js?

  47. Jorge says:

    Nice tutorial, I was trying your code and then i figure it out that it could be much simpler

    In de source method just surround the stateName in a span tag and give stateCode as attribute eg. data-state-code=”code”. In the updater method just use the jquery selector, so you can retrieve the code and the name

    source: function (query, proccess) {

    var results = new Array();

    $.each(states, function(index, state) {
    results.push(” + state.name + ”);
    });

    proccess(results);
    },

    updater: function (item) {

    var $item = $(item);

    // retrieve id|code for your benefits

    var code = $item.data(‘state-code’);

    return $item.text();
    }

  48. Jorge says:

    span html tags are not allowed :(… Then in this way:

    source: function (query, proccess) {

    ….var results = new Array();

    ….$.each(states, function(index, state) {

    ….results.push(‘span data-state-code=”‘+state-code+'”‘ + state.name + ‘/span’); });

    ….proccess(results);
    },

    updater: function (item) {

    ….var $item = $(item);

    ….// retrieve id|code for your benefits

    ….var code = $item.data(‘state-code’);
    ….alert(code);

    ….return $item.text();
    }

  49. […] File Name : How to use json objects with twitter bootstrap typeahead Source : tatiyants.com Download : How to use json objects with twitter bootstrap typeahead […]

  50. […] How to use json objects with twitter bootstrap typeahead […]