I'm working on a search functionality for my website and I'm using Bootstrap's typeahead to show the results. So far so good. But what I want is to extend the function so that I could add an image and some other item, say description, etc. According to this post, that is possible: custom typeahead.
Basically I need something like this as each result item:
<div class="resultContainer">
<div class="resultImage"><img /></div>
<div class="resultDesc"></div>
<div class="resultLabel"></div>
</div>
Now it's:
<li><a href="#"></a></li>
And this doesn't even work with a longer text than the width of the typeahead. So the text doesn't go to the next line and hence doesn't fit the <li>
. How can I use the the custom layout I want? (btw I have an array of arrays of results. Each sub-array contains img, desc, etc.). This is what I have right now:
Thanks in advance.
Use the highlighter
method:
$('.typeahead').typeahead({
highlighter: function(item){
return "<div>.......</div>";
}
});
Method used to highlight autocomplete results. Accepts a single argument item and has the scope of the typeahead instance. Should return html.
mgadda's answer neatly solves the issue for how to augment rendering items with custom data. Unfortunately this metadata isn't available once an item is selected, because bootstrap's select()
method calls your updater()
with a value taken from the DOM, not your loaded String:
var val = this.$menu.find('.active').attr('data-value');
One way around this is to set the metadata you need to DOM elements in highlighter()
, then find them in your updater()
. Since we only needed an integer, we set an ID to the image tag itself, and in updater, find it based on the image tag that's still visible:
$('.your_textboxes').typeahead({
highlighter: function(item) {
return('<img src="' + item.friend.img + '" id="klid_' + item.friend.id + '" />' + item);
},
updater: function(val) {
var klid = $('ul.typeahead li.active:visible a img');
if (klid && klid.length) {
klid = klid[0].id.substr(5);
// do stuff with metadata...
}
return(val);
}
Need more metadata? Wrap your highlighter in a span, or add some hidden form fields.
This feels kludgey though. If anyone has a cleaner solution, I'd love to see it.
Typeahead expects that everything passed into the process callback from the source callback will be a string. Unfortunately, this means that your highlighter callback is somewhat limited in the kind of HTML it can generate since you can only modify a string so much.
You can, however, define your source method such that it returns the usual array of string objects each of which have an additional data property that contains all the data you'll need to generate HTML in the highlighter.
$('.typeahead').typeahead
source: (query, processCallback)->
$.get '/users', q: query, (data)->
processCallback data.map (user)->
item = new String("#{user.first_name} #{user.last_name}")
item.data = user
item
In this form, item
will be passed around the internals of typeahead as a string, and when it finally reaches your custom highlighter, you can use the data property to build more complex html:
$('.typeahead').typeahead
highlighter: (item)->
"<img src=\"#{item.data.avatar_url}\" /> #{item}"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With