diff --git a/packages/primevue/src/listbox/Listbox.spec.js b/packages/primevue/src/listbox/Listbox.spec.js index 23084674c1..4bf70bdd78 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 33b69bf4a1..3683882a4d 100755 --- a/packages/primevue/src/listbox/Listbox.vue +++ b/packages/primevue/src/listbox/Listbox.vue @@ -703,17 +703,6 @@ export default { this.writeValue(value, event); this.$emit('change', { originalEvent: event, value }); }, - flatOptions(options) { - return (options || []).reduce((result, option, index) => { - result.push({ optionGroup: option, group: true, index }); - - const optionGroupChildren = this.getOptionGroupChildren(option); - - optionGroupChildren && optionGroupChildren.forEach((o) => result.push(o)); - - return result; - }, []); - }, listRef(el, contentRef) { this.list = el; contentRef && contentRef(el); // For VirtualScroller @@ -723,10 +712,25 @@ export default { } }, computed: { - visibleOptions() { - const options = this.optionGroupLabel ? this.flatOptions(this.options) : this.options || []; + optionsListFlat() { + return this.filterValue ? FilterService.filter(this.options, this.searchFields, this.filterValue, this.filterMatchMode, this.filterLocale) : this.options; + }, + optionsListGroup() { + const filteredOptions = []; - return this.filterValue ? FilterService.filter(options, this.searchFields, this.filterValue, this.filterMatchMode, this.filterLocale) : options; + (this.options || []).forEach((optionGroup) => { + const optionGroupChildren = this.getOptionGroupChildren(optionGroup) || []; + const filteredChildren = this.filterValue ? FilterService.filter(optionGroupChildren, this.searchFields, this.filterValue, this.filterMatchMode, this.filterLocale) : optionGroupChildren; + + if (filteredChildren?.length) { + filteredOptions.push({ optionGroup, group: true }, ...filteredChildren); + } + }); + + return filteredOptions; + }, + visibleOptions() { + return this.optionGroupLabel ? this.optionsListGroup : this.optionsListFlat; }, // @deprecated use $filled instead hasSelectedOption() {