Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typeahead.js - Search in multiple property values

Please see example below.

JSFiddle: http://jsfiddle.net/R7UvH/2/

How do I make typeahead.js (0.10.1) search for matches in more than one property value? Ideally, within whole data (data.title, data.desc and in all data.category[i].name)

 datumTokenizer: function(data) {
     // **search in other property values; e.g. data.title & data.desc etc..**
     return Bloodhound.tokenizers.whitespace(data.title);
 },

Whole example:

var data = [{
    title: "some title here",
    desc: "some option here",
    category: [{
        name: "category 1",
    }, {
        name: "categoy 2",
    }]
},
{
    title: "some title here",
    desc: "some option here",
    category: [{
        name: "category 1",
    }, {
        name: "categoy 2",
    }]
}];

var posts = new Bloodhound({
    datumTokenizer: function(data) {
        // **search in other property values; e.g. data.title & data.desc etc..**
        return Bloodhound.tokenizers.whitespace(data.title);
    },
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    local: data
});
posts.initialize();

$('#search-input').typeahead({
    highlight: true
}, {
    name: 'Pages',
    displayKey: 'title',
    source: posts.ttAdapter(),
    templates: {
        header: '<h3>Pages</h3>'
    }
});
like image 725
Iladarsda Avatar asked Feb 18 '14 10:02

Iladarsda


3 Answers

Typeahead 0.10.3 added "support to object tokenizers for multiple property tokenization."

So, your example becomes

var posts = new Bloodhound({
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('title', 'desc'),
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    local: data
});

However, I don't think this will work for properties nested inside, that is, the data.category object in your case.

As a side note, if you are using prefetched data, be sure to clear the local storage first, otherwise the new tokenizer won't take effect (Because datumTokenizer is used when adding to the search index, and if data is already present in localStorage, then the search index will not be updated). I was stuck on this for a while!

like image 96
Neelabh Avatar answered Nov 02 '22 04:11

Neelabh


return Bloodhound.tokenizers.whitespace(data.title) returns an array of strings.

So, instead of returning that value: save it (and your other desired values), then concatenate them and return that value...

x = Bloodhound.tokenizers.whitespace(data.title);
y = Bloodhound.tokenizers.whitespace(data.desc);
z = Bloodhound.tokenizers.whitespace(data.category[i].name);
return x.concat(y).concat(z);
like image 14
Timothy Aaron Avatar answered Nov 02 '22 04:11

Timothy Aaron


I've implemented a solution here:

http://jsfiddle.net/Fresh/4nnnG/

As you have a local datasource you need to create individual datasets to enable you to match on multiple data properties. e.g.

$('#search-input').typeahead({
    highlight: true
}, {
    name: 'titles',
    displayKey: 'title',
    source: titles.ttAdapter()
}, {
    name: 'descs',
    displayKey: 'desc',
    source: descs.ttAdapter()
}, {
    name: 'cats',
    displayKey: 'name',
    source: cats.ttAdapter()
});
like image 7
Ben Smith Avatar answered Nov 02 '22 06:11

Ben Smith