From 527670e6e71872e09fa98694f443b572847a89ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Vannicatte?= <20689156+shortcuts@users.noreply.github.com> Date: Tue, 25 May 2021 18:14:34 +0200 Subject: [PATCH] fix(js): do not render empty sections (#594) --- cypress/test-apps/js/categoriesPlugin.tsx | 6 +- examples/instantsearch/src/autocomplete.tsx | 10 +- .../multiple-datasets-with-headers/app.tsx | 12 +- .../categoriesPlugin.tsx | 6 +- examples/playground/categoriesPlugin.tsx | 6 +- examples/preview-panel-in-modal/app.tsx | 6 +- .../app.tsx | 8 +- .../recentlyViewedItemsPlugin.tsx | 6 +- .../src/__tests__/render.test.ts | 78 ++++++++- packages/autocomplete-js/src/render.tsx | 158 +++++++++--------- 10 files changed, 169 insertions(+), 127 deletions(-) diff --git a/cypress/test-apps/js/categoriesPlugin.tsx b/cypress/test-apps/js/categoriesPlugin.tsx index d6ec7e8c6..3dd045d8d 100644 --- a/cypress/test-apps/js/categoriesPlugin.tsx +++ b/cypress/test-apps/js/categoriesPlugin.tsx @@ -36,11 +36,7 @@ export function createCategoriesPlugin({ }); }, templates: { - header({ items }) { - if (items.length === 0) { - return null; - } - + header() { return ( Categories diff --git a/examples/instantsearch/src/autocomplete.tsx b/examples/instantsearch/src/autocomplete.tsx index 53d499e2f..31c75ad10 100644 --- a/examples/instantsearch/src/autocomplete.tsx +++ b/examples/instantsearch/src/autocomplete.tsx @@ -151,11 +151,7 @@ const querySuggestionsPluginInCategory = createQuerySuggestionsPlugin({ }, templates: { ...source.templates, - header({ items }) { - if (items.length === 0) { - return null; - } - + header() { return ( In {currentCategory} @@ -232,8 +228,8 @@ const querySuggestionsPlugin = createQuerySuggestionsPlugin({ }, templates: { ...source.templates, - header({ items }) { - if (!currentCategory || items.length === 0) { + header() { + if (!currentCategory) { return null; } diff --git a/examples/multiple-datasets-with-headers/app.tsx b/examples/multiple-datasets-with-headers/app.tsx index 035cefd92..2855d2634 100644 --- a/examples/multiple-datasets-with-headers/app.tsx +++ b/examples/multiple-datasets-with-headers/app.tsx @@ -20,11 +20,7 @@ const recentSearchesPlugin = createLocalStorageRecentSearchesPlugin({ ...source, templates: { ...source.templates, - header({ items }) { - if (items.length === 0) { - return null; - } - + header() { return ( Your searches @@ -49,11 +45,7 @@ const querySuggestionsPlugin = createQuerySuggestionsPlugin({ ...source, templates: { ...source.templates, - header({ items, state }) { - if (items.length === 0) { - return null; - } - + header({ state }) { return ( diff --git a/examples/multiple-datasets-with-headers/categoriesPlugin.tsx b/examples/multiple-datasets-with-headers/categoriesPlugin.tsx index 43cfb8275..fee78a7dd 100644 --- a/examples/multiple-datasets-with-headers/categoriesPlugin.tsx +++ b/examples/multiple-datasets-with-headers/categoriesPlugin.tsx @@ -36,11 +36,7 @@ export function createCategoriesPlugin({ }); }, templates: { - header({ items }) { - if (items.length === 0) { - return null; - } - + header() { return ( Categories diff --git a/examples/playground/categoriesPlugin.tsx b/examples/playground/categoriesPlugin.tsx index 46ca0f025..b3252f8b1 100644 --- a/examples/playground/categoriesPlugin.tsx +++ b/examples/playground/categoriesPlugin.tsx @@ -36,11 +36,7 @@ export function createCategoriesPlugin({ }); }, templates: { - header({ items }) { - if (items.length === 0) { - return null; - } - + header() { return ( Categories diff --git a/examples/preview-panel-in-modal/app.tsx b/examples/preview-panel-in-modal/app.tsx index d95d3956e..ea54eb2ee 100644 --- a/examples/preview-panel-in-modal/app.tsx +++ b/examples/preview-panel-in-modal/app.tsx @@ -84,11 +84,7 @@ autocomplete({ refresh(); }, templates: { - header({ items, Fragment }) { - if (items.length === 0) { - return null; - } - + header({ Fragment }) { return ( diff --git a/examples/query-suggestions-with-recent-searches/app.tsx b/examples/query-suggestions-with-recent-searches/app.tsx index d80830ae5..4743cf110 100644 --- a/examples/query-suggestions-with-recent-searches/app.tsx +++ b/examples/query-suggestions-with-recent-searches/app.tsx @@ -19,8 +19,8 @@ const recentSearchesPlugin = createLocalStorageRecentSearchesPlugin({ ...source, templates: { ...source.templates, - header({ items, state }) { - if (Boolean(state.query) || items.length === 0) { + header({ state }) { + if (state.query) { return null; } @@ -48,8 +48,8 @@ const querySuggestionsPlugin = createQuerySuggestionsPlugin({ ...source, templates: { ...source.templates, - header({ items, state }) { - if (Boolean(state.query) || items.length === 0) { + header({ state }) { + if (state.query) { return null; } diff --git a/examples/recently-viewed-items/recentlyViewedItemsPlugin.tsx b/examples/recently-viewed-items/recentlyViewedItemsPlugin.tsx index 93bc484af..cf61b08ab 100644 --- a/examples/recently-viewed-items/recentlyViewedItemsPlugin.tsx +++ b/examples/recently-viewed-items/recentlyViewedItemsPlugin.tsx @@ -71,11 +71,7 @@ export function createLocalStorageRecentlyViewedItems< }, templates: { ...transformedSource.templates, - header({ items }) { - if (items.length === 0) { - return null; - } - + header() { return ( Recently viewed diff --git a/packages/autocomplete-js/src/__tests__/render.test.ts b/packages/autocomplete-js/src/__tests__/render.test.ts index ceeab1214..1ea8b21b2 100644 --- a/packages/autocomplete-js/src/__tests__/render.test.ts +++ b/packages/autocomplete-js/src/__tests__/render.test.ts @@ -9,6 +9,9 @@ import { import { autocomplete } from '../autocomplete'; describe('render', () => { + const sourceId1 = 'testSource1'; + const sourceId2 = 'testSource2'; + beforeEach(() => { document.body.innerHTML = ''; }); @@ -181,8 +184,6 @@ describe('render', () => { }); test('provides the elements', async () => { - const sourceId1 = 'testSource1'; - const sourceId2 = 'testSource2'; const container = document.createElement('div'); const panelContainer = document.createElement('div'); @@ -253,8 +254,6 @@ describe('render', () => { }); test('provides the sections', async () => { - const sourceId1 = 'testSource1'; - const sourceId2 = 'testSource2'; const container = document.createElement('div'); const panelContainer = document.createElement('div'); @@ -536,4 +535,75 @@ describe('render', () => { }, }); }); + + test('does not render the sections without results and noResults template on multi sources', async () => { + const container = document.createElement('div'); + const panelContainer = document.createElement('div'); + + document.body.appendChild(panelContainer); + autocomplete<{ label: string }>({ + container, + panelContainer, + openOnFocus: true, + getSources() { + return [ + { + sourceId: sourceId1, + getItems() { + return []; + }, + templates: { + header() { + return sourceId1; + }, + item({ item }) { + return item.label; + }, + footer() { + return sourceId1; + }, + }, + }, + { + sourceId: sourceId2, + getItems() { + return [{ label: '2' }]; + }, + templates: { + header() { + return sourceId2; + }, + item({ item }) { + return item.label; + }, + footer() { + return sourceId2; + }, + }, + }, + ]; + }, + }); + + const input = container.querySelector('.aa-Input'); + + fireEvent.input(input, { target: { value: 'a' } }); + + await waitFor(() => { + expect( + panelContainer.querySelector('.aa-Panel') + ).toBeInTheDocument(); + + expect( + panelContainer.querySelector( + `[data-autocomplete-source-id="${sourceId1}"]` + ) + ).not.toBeInTheDocument(); + expect( + panelContainer.querySelector( + `[data-autocomplete-source-id="${sourceId2}"]` + ) + ).toBeInTheDocument(); + }); + }); }); diff --git a/packages/autocomplete-js/src/render.tsx b/packages/autocomplete-js/src/render.tsx index 0e21cea1c..30cb4d80d 100644 --- a/packages/autocomplete-js/src/render.tsx +++ b/packages/autocomplete-js/src/render.tsx @@ -90,87 +90,91 @@ export function renderPanel( dom.panel.classList.toggle('aa-Panel--stalled', state.status === 'stalled'); - const sections = state.collections.map(({ source, items }, sourceIndex) => ( -
- {source.templates.header && ( -
- {source.templates.header({ - components, - createElement, - Fragment, - items, - source, - state, - })} -
- )} + const sections = state.collections + .filter( + ({ source, items }) => source.templates.noResults || items.length > 0 + ) + .map(({ source, items }, sourceIndex) => ( +
+ {source.templates.header && ( +
+ {source.templates.header({ + components, + createElement, + Fragment, + items, + source, + state, + })} +
+ )} - {source.templates.noResults && items.length === 0 ? ( -
- {source.templates.noResults({ - components, - createElement, - Fragment, - source, - state, - })} -
- ) : ( -
    - {items.map((item) => { - const itemProps = autocomplete.getItemProps({ - item, + {source.templates.noResults && items.length === 0 ? ( +
    + {source.templates.noResults({ + components, + createElement, + Fragment, source, - }); + state, + })} +
    + ) : ( +
      + {items.map((item) => { + const itemProps = autocomplete.getItemProps({ + item, + source, + }); - return ( -
    • - {source.templates.item({ - components, - createElement, - Fragment, - item, - state, - })} -
    • - ); - })} -
    - )} + return ( +
  • + {source.templates.item({ + components, + createElement, + Fragment, + item, + state, + })} +
  • + ); + })} +
+ )} - {source.templates.footer && ( -
- {source.templates.footer({ - components, - createElement, - Fragment, - items, - source, - state, - })} -
- )} -
- )); + {source.templates.footer && ( +
+ {source.templates.footer({ + components, + createElement, + Fragment, + items, + source, + state, + })} +
+ )} +
+ )); const children = (