From af38284410ec42ff79317be7dc784de8559de8e2 Mon Sep 17 00:00:00 2001 From: Andy Ghiuta Date: Sat, 12 Jan 2019 09:29:47 +0200 Subject: [PATCH] Keep already selected values when selecting others with filter --- package.json | 1 + src/components/AdvancedSelect.vue | 43 ++++++++++++++++++------------- tests/unit/AdvancedSelect.spec.js | 24 +++++++++++++++++ 3 files changed, 50 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 59b3499..f9473fd 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "build": "node build.js", "lint": "vue-cli-service lint", "test:unit": "vue-cli-service test:unit", + "test:unit-watch": "vue-cli-service test:unit --watch", "preversion": "npm run test:unit && npm run build && git add -A dist", "postversion": "git push && git push --tags && echo Run: \"npm publish\"" }, diff --git a/src/components/AdvancedSelect.vue b/src/components/AdvancedSelect.vue index 96d3190..2473181 100644 --- a/src/components/AdvancedSelect.vue +++ b/src/components/AdvancedSelect.vue @@ -221,7 +221,9 @@ export default { return this.values.join(', '); }, optionsMap() { - return this.getOptionsMap(this.filtered); + // For the optionsMap, use all options, not just the filtered ones + // so that selecting values searches entire list + return this.getOptionsMap(this.linearOptions); }, selected() { let selected = {}; @@ -241,24 +243,24 @@ export default { } return selected; }, + /** + * Create a list of the filtered options; i.e. those that match the search + */ filtered() { + return this.linearOptions.filter(this.optionMatch); + }, + /** + * Create a linear list of all the options (headers included) + */ + linearOptions() { return this.options.reduce((f, o) => { if (o.options) { - // filter this group - const group = o.options.filter(this.optionMatch); - if (this.textMatch(o.label) || group.length) { - // push the header - f.push({ - header: o.label, - }); - // push the rest of the items - if (group.length) { - f.push(...group); - } else { - f.push(...o.options); - } - } - } else if (this.optionMatch(o)) { + // push the header + f.push({ + header: o.label, + }); + f.push(...o.options); + } else { // it's an item without group, push it to the list f.push(o); } @@ -316,7 +318,7 @@ export default { }, map); }, optionMatch(o) { - return this.textMatch(o.text); + return this.textMatch(o.text || o.header); }, textMatch(text) { return this.filterRegExp.test(text); @@ -347,7 +349,12 @@ export default { this.myValue = newVal; }, selectAll() { - this.myValue = this.filtered.filter(o => !o.header && !o.disabled).map(o => o.value); + // when selecting all, concatenate the exiting selected values + // with the currently filtered ones + this.myValue = [].concat( + this.myValue || [], + this.filtered.filter(o => !o.header && !o.disabled).map(o => o.value) + ); }, selectNone() { this.myValue = []; diff --git a/tests/unit/AdvancedSelect.spec.js b/tests/unit/AdvancedSelect.spec.js index 2fd30f1..f109c53 100644 --- a/tests/unit/AdvancedSelect.spec.js +++ b/tests/unit/AdvancedSelect.spec.js @@ -230,8 +230,32 @@ describe('AdvancedSelect.vue', () => { const links = wrapper.findAll('div.btn-group > ul > li .btn-group button'); links.at(0).trigger('click'); expect(wrapper.emitted().input).to.exist; + expect(wrapper.emitted().input[0][0]).to.deep.equal([1, 2, 3]); expect(wrapper.emitted().input[0][0].length).to.equal(3); + }); + it('Disabled values are not set on "Select all"', () => { + const wrapper = shallowMount(Select, { + propsData: { + options: [ + { text: '1', value: 1 }, + { text: '2', value: 2 }, + { + label: 'Group', + options: [ + { text: '3', value: 3 }, + { text: '4', value: 4, disabled: true }, + ], + }, + ], + multiple: true, + controls: true, + }, + }); + const links = wrapper.findAll('div.btn-group > ul > li .btn-group button'); + links.at(0).trigger('click'); + expect(wrapper.emitted().input).to.exist; expect(wrapper.emitted().input[0][0]).to.deep.equal([1, 2, 3]); + expect(wrapper.emitted().input[0][0].length).to.equal(3); }); it('No values are set on "Select none"', () => { const wrapper = shallowMount(Select, {