From 06563081496c431add533a10e6dc8736236e40aa Mon Sep 17 00:00:00 2001 From: uros Date: Thu, 22 Aug 2024 12:56:47 +0200 Subject: [PATCH] fix: Listbox: Preserve option groups while filtering. chore: Add unit tests fixes #6233 --- packages/primevue/src/listbox/Listbox.spec.js | 65 +++++++++++++++++++ packages/primevue/src/listbox/Listbox.vue | 22 ++++++- 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/packages/primevue/src/listbox/Listbox.spec.js b/packages/primevue/src/listbox/Listbox.spec.js index 23084674c..4bf70bdd7 100644 --- a/packages/primevue/src/listbox/Listbox.spec.js +++ b/packages/primevue/src/listbox/Listbox.spec.js @@ -47,5 +47,70 @@ describe('Listbox.vue', () => { expect(icon.classes()).toContain('pi-discord'); }); + + it('should correctly filter', async () => { + await wrapper.setProps({ + filter: true + }); + + const filterInput = wrapper.find('input.p-listbox-filter'); + + expect(filterInput.exists()).toBe(true); + + await filterInput.setValue('is'); + + const options = wrapper.findAll('.p-listbox-option'); + + expect(options.length).toBe(2); + expect(options[0].text()).toBe('Istanbul'); + }); + + it('should correctly filter groups', async () => { + await wrapper.setProps({ + filter: true, + optionGroupLabel: 'label', + optionLabel: 'label', + optionGroupChildren: 'items', + options: [ + { + label: 'Germany', + code: 'DE', + items: [ + { label: 'Berlin', value: 'Berlin' }, + { label: 'Frankfurt', value: 'Frankfurt' }, + { label: 'Hamburg', value: 'Hamburg' }, + { label: 'Munich', value: 'Munich' } + ] + }, + { + label: 'USA', + code: 'US', + items: [ + { label: 'Chicago', value: 'Chicago' }, + { label: 'Los Angeles', value: 'Los Angeles' }, + { label: 'New York', value: 'New York' }, + { label: 'San Francisco', value: 'San Francisco' } + ] + } + ] + }); + + const filterInput = wrapper.find('input.p-listbox-filter'); + + expect(filterInput.exists()).toBe(true); + + await filterInput.setValue('ch'); + + const optionGroups = wrapper.findAll('.p-listbox-option-group'); + const options = wrapper.findAll('.p-listbox-option'); + + expect(optionGroups.length).toBe(2); + expect(optionGroups[0].text()).toBe('Germany'); + expect(optionGroups[1].text()).toBe('USA'); + + expect(options.length).toBe(2); + expect(options[0].text()).toBe('Munich'); + expect(options[1].text()).toBe('Chicago'); + }); }); }); diff --git a/packages/primevue/src/listbox/Listbox.vue b/packages/primevue/src/listbox/Listbox.vue index 04cc524cc..ebad55ec9 100755 --- a/packages/primevue/src/listbox/Listbox.vue +++ b/packages/primevue/src/listbox/Listbox.vue @@ -726,7 +726,27 @@ export default { visibleOptions() { const options = this.optionGroupLabel ? this.flatOptions(this.options) : this.options || []; - return this.filterValue ? FilterService.filter(options, this.searchFields, this.filterValue, this.filterMatchMode, this.filterLocale) : options; + if (this.filterValue) { + const filteredOptions = FilterService.filter(options, this.searchFields, this.filterValue, this.filterMatchMode, this.filterLocale); + + if (this.optionGroupLabel) { + const optionGroups = this.options || []; + const filtered = []; + + optionGroups.forEach((group) => { + const groupChildren = this.getOptionGroupChildren(group); + const filteredItems = groupChildren.filter((item) => filteredOptions.includes(item)); + + if (filteredItems.length > 0) filtered.push({ ...group, [typeof this.optionGroupChildren === 'string' ? this.optionGroupChildren : 'items']: [...filteredItems] }); + }); + + return this.flatOptions(filtered); + } + + return filteredOptions; + } + + return options; }, hasSelectedOption() { return isNotEmpty(this.modelValue);