tomsouthall / turnstone

React customisable autocomplete component with typeahead and grouped results from multiple APIs.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Data That Is Already Grouped

pspaulding opened this issue · comments

First of all, very cool library! I can tell you put a lot of thought into it. Unless I'm not understanding something, the library assumes that the data will be assembled from multiple APIs. What if that is not the case? What if the API can already group the data (in my case, using graphql)? It seems inefficient to make multiple API calls when I don't need to. I think a slight change to the API would really open the use cases for this library.

Multiple APIs

const listbox = async query => {
  const [cities, airports] = await Promise.all([
    fetch(`/api/cities?q=${encodeURIComponent(query)}&limit=${maxItems}`).then(res => res.json()),
    fetch(`/api/airports?q=${encodeURIComponent(query)}&limit=${maxItems}`).then(res => res.json())
  ]);
  return [
    {
      id: 'cities',
      name: 'Cities',
      ratio: 8,
      displayField: 'name',
      data: cities,
      searchType: 'startswith'
    },
    {
      id: 'airports',
      name: 'Airports',
      ratio: 2,
      displayField: 'name',
      data: airports,
      searchType: 'contains'
    }
  ];
};

API that Already Groups Results

const listbox = async query => {
  const alreadyGroupedData = await fetch(`/api/grouped-data?q=${encodeURIComponent(query)}&limit=${maxItems}`)
    .then(res => res.json());
  return [
    {
      id: 'cities',
      name: 'Cities',
      ratio: 8,
      displayField: 'name',
      data: alreadyGroupedData.cities,
      searchType: 'startswith'
    },
    {
      id: 'airports',
      name: 'Airports',
      ratio: 2,
      displayField: 'name',
      data: alreadyGroupedData.airports,
      searchType: 'contains'
    }
  ];
};

Thank you! This would be a great enhancement and makes a ton of sense. I'll add this to the backlog and respond to this issue when I have an update. Hopefully soon!

@pspaulding v1.3.0 of Turnstone has just been released. Hopefully this will allow you to do what you were looking for.

The listbox and defaultListbox props can still be supplied as an array or object as in previous versions. But, in addition, they can now be supplied as a function.

The listbox prop would look something like the following example. It accepts the query as the sole argument and must return a promise that resolves to an array.

const listbox = (query) => fetch(`/api/locations?q=${encodeURIComponent(query)}`)
  .then(res => res.json())
  .then(locations => {
    const {cities, airports} = locations

    return [
      {
        id: 'cities',
        name: 'Cities',
        ratio: 8,
        displayField: 'name',
        data: cities,
        searchType: 'startswith'
      },
      {
        id: 'airports',
        name: 'Airports',
        ratio: 2,
        displayField: 'name',
        data: airports,
        searchType: 'contains'
      }
    ]
  })

Thanks again for the suggestion! This makes the definition of listbox groups super flexible.

Awesome!