Skip to content

Commit b25c140

Browse files
committed
fix(js): do not render empty sections
1 parent 67e7bbf commit b25c140

2 files changed

Lines changed: 155 additions & 81 deletions

File tree

packages/autocomplete-js/src/__tests__/render.test.ts

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import {
99
import { autocomplete } from '../autocomplete';
1010

1111
describe('render', () => {
12+
const sourceId1 = 'testSource1';
13+
const sourceId2 = 'testSource2';
14+
1215
beforeEach(() => {
1316
document.body.innerHTML = '';
1417
});
@@ -181,8 +184,6 @@ describe('render', () => {
181184
});
182185

183186
test('provides the elements', async () => {
184-
const sourceId1 = 'testSource1';
185-
const sourceId2 = 'testSource2';
186187
const container = document.createElement('div');
187188
const panelContainer = document.createElement('div');
188189

@@ -253,8 +254,6 @@ describe('render', () => {
253254
});
254255

255256
test('provides the sections', async () => {
256-
const sourceId1 = 'testSource1';
257-
const sourceId2 = 'testSource2';
258257
const container = document.createElement('div');
259258
const panelContainer = document.createElement('div');
260259

@@ -536,4 +535,75 @@ describe('render', () => {
536535
},
537536
});
538537
});
538+
539+
test('does not render the sections without results and noResults template on multi sources', async () => {
540+
const container = document.createElement('div');
541+
const panelContainer = document.createElement('div');
542+
543+
document.body.appendChild(panelContainer);
544+
autocomplete<{ label: string }>({
545+
container,
546+
panelContainer,
547+
openOnFocus: true,
548+
getSources() {
549+
return [
550+
{
551+
sourceId: sourceId1,
552+
getItems() {
553+
return [];
554+
},
555+
templates: {
556+
header() {
557+
return sourceId1;
558+
},
559+
item({ item }) {
560+
return item.label;
561+
},
562+
footer() {
563+
return sourceId1;
564+
},
565+
},
566+
},
567+
{
568+
sourceId: sourceId2,
569+
getItems() {
570+
return [{ label: '2' }];
571+
},
572+
templates: {
573+
header() {
574+
return sourceId2;
575+
},
576+
item({ item }) {
577+
return item.label;
578+
},
579+
footer() {
580+
return sourceId2;
581+
},
582+
},
583+
},
584+
];
585+
},
586+
});
587+
588+
const input = container.querySelector<HTMLInputElement>('.aa-Input');
589+
590+
fireEvent.input(input, { target: { value: 'a' } });
591+
592+
await waitFor(() => {
593+
expect(
594+
panelContainer.querySelector<HTMLElement>('.aa-Panel')
595+
).toBeInTheDocument();
596+
597+
expect(
598+
panelContainer.querySelector(
599+
`[data-autocomplete-source-id="${sourceId1}"]`
600+
)
601+
).not.toBeInTheDocument();
602+
expect(
603+
panelContainer.querySelector(
604+
`[data-autocomplete-source-id="${sourceId2}"]`
605+
)
606+
).toBeInTheDocument();
607+
});
608+
});
539609
});

packages/autocomplete-js/src/render.tsx

Lines changed: 81 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -90,87 +90,91 @@ export function renderPanel<TItem extends BaseItem>(
9090

9191
dom.panel.classList.toggle('aa-Panel--stalled', state.status === 'stalled');
9292

93-
const sections = state.collections.map(({ source, items }, sourceIndex) => (
94-
<section
95-
key={sourceIndex}
96-
className={classNames.source}
97-
data-autocomplete-source-id={source.sourceId}
98-
>
99-
{source.templates.header && (
100-
<div className={classNames.sourceHeader}>
101-
{source.templates.header({
102-
components,
103-
createElement,
104-
Fragment,
105-
items,
106-
source,
107-
state,
108-
})}
109-
</div>
110-
)}
93+
const sections = state.collections
94+
.filter(
95+
({ source, items }) => source.templates.noResults || items.length !== 0
96+
)
97+
.map(({ source, items }, sourceIndex) => (
98+
<section
99+
key={sourceIndex}
100+
className={classNames.source}
101+
data-autocomplete-source-id={source.sourceId}
102+
>
103+
{source.templates.header && (
104+
<div className={classNames.sourceHeader}>
105+
{source.templates.header({
106+
components,
107+
createElement,
108+
Fragment,
109+
items,
110+
source,
111+
state,
112+
})}
113+
</div>
114+
)}
111115

112-
{source.templates.noResults && items.length === 0 ? (
113-
<div className={classNames.sourceNoResults}>
114-
{source.templates.noResults({
115-
components,
116-
createElement,
117-
Fragment,
118-
source,
119-
state,
120-
})}
121-
</div>
122-
) : (
123-
<ul
124-
className={classNames.list}
125-
{...propGetters.getListProps({
126-
state,
127-
props: autocomplete.getListProps({}),
128-
...autocompleteScopeApi,
129-
})}
130-
>
131-
{items.map((item) => {
132-
const itemProps = autocomplete.getItemProps({
133-
item,
116+
{source.templates.noResults && items.length === 0 ? (
117+
<div className={classNames.sourceNoResults}>
118+
{source.templates.noResults({
119+
components,
120+
createElement,
121+
Fragment,
134122
source,
135-
});
123+
state,
124+
})}
125+
</div>
126+
) : (
127+
<ul
128+
className={classNames.list}
129+
{...propGetters.getListProps({
130+
state,
131+
props: autocomplete.getListProps({}),
132+
...autocompleteScopeApi,
133+
})}
134+
>
135+
{items.map((item) => {
136+
const itemProps = autocomplete.getItemProps({
137+
item,
138+
source,
139+
});
136140

137-
return (
138-
<li
139-
key={itemProps.id}
140-
className={classNames.item}
141-
{...propGetters.getItemProps({
142-
state,
143-
props: itemProps,
144-
...autocompleteScopeApi,
145-
})}
146-
>
147-
{source.templates.item({
148-
components,
149-
createElement,
150-
Fragment,
151-
item,
152-
state,
153-
})}
154-
</li>
155-
);
156-
})}
157-
</ul>
158-
)}
141+
return (
142+
<li
143+
key={itemProps.id}
144+
className={classNames.item}
145+
{...propGetters.getItemProps({
146+
state,
147+
props: itemProps,
148+
...autocompleteScopeApi,
149+
})}
150+
>
151+
{source.templates.item({
152+
components,
153+
createElement,
154+
Fragment,
155+
item,
156+
state,
157+
})}
158+
</li>
159+
);
160+
})}
161+
</ul>
162+
)}
159163

160-
{source.templates.footer && (
161-
<div className={classNames.sourceFooter}>
162-
{source.templates.footer({
163-
components,
164-
createElement,
165-
Fragment,
166-
items,
167-
source,
168-
state,
169-
})}
170-
</div>
171-
)}
172-
</section>
173-
));
164+
{source.templates.footer && (
165+
<div className={classNames.sourceFooter}>
166+
{source.templates.footer({
167+
components,
168+
createElement,
169+
Fragment,
170+
items,
171+
source,
172+
state,
173+
})}
174+
</div>
175+
)}
176+
</section>
177+
));
174178

175179
const children = (
176180
<Fragment>

0 commit comments

Comments
 (0)