0

I'm trying to use Typeahead.js (v0.11.1) + Bloodhound to display the results of a query. The query searches a list of users and returns matches based on either email, last_name, or first_name. If I query smi the matches look like this:

[{"email":"john@email.com","last_name":"Smith","first_name":"John"},
{"email":"bob@email.com","last_name":"Smith","first_name":"Bob"}]

My Bloodhound engine looks like this:

var userSearch = new Bloodhound({
    datumTokenizer: function (user) {
        return Bloodhound.tokenizers.obj.whitespace(user.email, user.last_name, user.first_name);
    },
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    remote: {
        url: '/search/users?query=%QUERY',
        wildcard: '%QUERY'
    }
});

The problem is Typeahead only shows a match when there is one JSON object, if it returns an array of objects, like the example above, then no matches.

I tried adding a transform to the remote, but then no matches were returned at all:

transform: function(users) {
    return $.map(users, function(user) {
        return {
            email: user.email,
            last_name: user.last_name,
            first_name: user.first_name
        }
    });
}
upful
  • 850
  • 10
  • 26

1 Answers1

3

The problem was with the datumTokenizer, you must concatenate the tokens like this:

datumTokenizer: function (user) {
    var emailTokens = Bloodhound.tokenizers.whitespace(user.email);
    var lastNameTokens = Bloodhound.tokenizers.whitespace(user.last_name);
    var firstNameTokens = Bloodhound.tokenizers.whitespace(user.first_name);
    return emailTokens.concat(lastNameTokens).concat(firstNameTokens);
}

Also you still need to use the transform on the remote. But now you can match an any of the three properties from each JSON object.

upful
  • 850
  • 10
  • 26