Grouping suggestions with sub headings in Typeahead
Asked Answered
L

1

6

I've got an instance of Typeahead pulling in a remote JSON object that lists airports, and I need to group them in the suggestions by 'location groups', as in the image below:

enter image description here

...and here's an example of how the JSON is formatted:

{
   "locations":[
  {
     "name":"London Intl Apt (YXU), Middlesex, Ontario, Canada",
     "type":"airport",
     "id":"528cc236e4b0ec1df53b21af",
     "iata":"YXU",
     "locationGroup":"",
     "locationGroupName":""
  },
  {
     "name":"London - Gatwick Apt (LGW), West Sussex, England, United Kingdom",
     "type":"airport",
     "id":"528cc236e4b0ec1df53b28cb",
     "iata":"LGW",
     "locationGroup":"LON",
     "locationGroupName":"London - All Airports (LON)"
  },
  {
     "name":"London - Heathrow Apt (LHR), Greater London, England, United Kingdom",
     "type":"airport",
     "id":"528cc236e4b0ec1df53b28b1",
     "iata":"LHR",
     "locationGroup":"LON",
     "locationGroupName":"London - All Airports (LON)"
  }
 ]
}

So where an item has a 'locationGroup' value it should be grouped with all other items with the same 'locationGroup'. If there is no 'locationGroup' it should just be listed individually.

I'm guessing that (assuming this is possible) this should be done when I'm setting up the Bloodhound engine - possibly within the Filter - but I'm really struggling to work out how. Can anybody help with this?

Location answered 3/3, 2014 at 9:58 Comment(2)
Does your URL for getting the array of "locations" data allow you to filter on "locationGroup"?Get
No, unfortunately I can only search by 'name'Location
A
2

Unfortunately, it seems the only way to get headers and sections in your Typeahead.js is to follow their Multiple Sections with Headers example. Their code is not entirely complete as to what they are doing so I'll try and mimic your code and their example.

// Get the data
var londonUk = new Bloodhound({
   datumTokenizer: function(d) { return Bloodhound.tokenizers.whitespace(d.name); },
   queryTokenizer: Bloodhound.tokenizers.whitespace,
   prefetch: '../data/londonUk.json'
});

var londonCa = new Bloodhound({
   datumTokenizer: function(d) { return Bloodhound.tokenizers.whitespace(d.name); },
   queryTokenizer: Bloodhound.tokenizers.whitespace,
   prefetch: '../data/londonCa.json'
});

// Intialize the Bloodhound
londonUk.initialize();
londonCa.initialize();

// Set up Typeahead
$('.transit-search .typeahead').typeahead({
   highlight: true
},
{
   name: 'London UK All Airports',
   displayKey: 'name',
   source: londonUk.ttAdapter(),
   templates: {
       // This is the group header that will be shown at the top of a grouping
       header: '<h3 class="group-name">London - All Airports (LON)</h3>',
       // These will be the templates for the items within a group.
       suggestion: Handlebars.compile(['<p class="indent">{{name}} {{type}}</p>'])
   }
},
{
   name: 'London CA All Airports',
   displayKey: 'name',
   source: londonCa.ttAdapter(),
   templates: {
       header: '<h3 class="group-name">London, ON, Canada - All Airports</h3>',
       suggestion: Handlebars.compile(['<p class="indent">{{name}} {{type}}</p>'])
   }
});

The difficulty here lies in making your data work with the way that Typeahead.js wants the data structured so it can make groups out of it. You could pass back one giant JSON file and then sort out each airport into its own list that you can then use as a local data variable for each of the Bloodhound initializations or you could make a query for every JSON file and airport you support, like I've done with the example above.

The first one would probably be more consistent and makes considerably less hits to the server but will require some data massaging to get going but you already have a variable for the group in each item so this shouldn't be too difficult. This will require a lot of initialization but I think the grouping will work out just as you want it to.

Autobahn answered 3/3, 2014 at 17:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.