I'm currently using typeahead.js with the searchkick rails gem to search and autocomplete queries. With the necessary adjustments to my controller I am now searching for records across two models (Artists and Albums):
class SearchController < ApplicationController
...
def autocomplete
@results = Artist.search(params[:query], index_name: [Artist.searchkick_index.name, Album.searchkick_index.name], fields: [{ name: :word_start }], limit: 10)
render json: @results
end
end
resources :search, only: :index do
collection do
get :autocomplete
end
end
Search suggestions for the two are retrieved as expected but I now need to group the two in their own templates. This has led me to looking into using Multiple Datasets.
In my js file I'm retrieving results using the remote
as suggested in this post:
remote: {
url: "/search/autocomplete?query=%QUERY",
wildcard: "%QUERY"
}
Unlike what I have, the docs suggest pulling from the model's index action by using the prefetch
option:
prefetch: '../data/nhl.json'
Unfortunately configuring my js in this manner gives me nothing. Presumably I'd need an albums
variable but would it not just be identical to how I have my artists
variable setup? How would I go about in configuring this based on the JS I have now?
$(function() {
var artists = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace("artist"),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: "/search/autocomplete?query=%QUERY",
wildcard: "%QUERY"
}
});
artists.initialize();
$(".search").typeahead(null, {
displayKey: "name",
source: artists.ttAdapter(),
templates: {
header: "<h3>Artists</h3>",
suggestion: function(data) {
return "<a href=" + data.url + ">"+ data.name +"</a>";
}
},
{
// Albums would go here
}
});
});
Returned JSON
/* artists.json */
{
id: 1,
name: "50 Cent",
avatar: ...,
url: "/artists/1"
}
/* albums.json */
{
id: 1,
name: "Get Rich or Die Tryin'",
artwork: ...,
genre: "Hip-Hop/Rap",
release_date: ...,
url: "/albums/1"
}
Try using suggestion
property of templates
to filter displayed results using url
of returned data
, RegExp.prototype.test()
$(".search").typeahead(null, {
displayKey: "name",
source: artists.ttAdapter(),
templates: {
// header: "<h3>Artists</h3>",
suggestion: function(data) {
var temp;
if (/^\/albums/.test(data.url)) {
// albums template
// temp = "albums template"
} else {
// temp = "artists template"
}
return temp;
}
}
});
});