diff --git a/src/Webform.js b/src/Webform.js index 48de614951..dd0e48f204 100644 --- a/src/Webform.js +++ b/src/Webform.js @@ -937,7 +937,9 @@ export default class Webform extends NestedDataComponent { }; } // Metadata needs to be available before setValue - this._submission.metadata = submission.metadata || {}; + this._submission.metadata = submission.metadata + ? _.cloneDeep(submission.metadata) + : {}; this.editing = !!submission._id; // Set the timezone in the options if available. diff --git a/src/WebformBuilder.unit.js b/src/WebformBuilder.unit.js index 27d34ea946..6e3c3c6310 100644 --- a/src/WebformBuilder.unit.js +++ b/src/WebformBuilder.unit.js @@ -9,6 +9,9 @@ import testApiKeysUniquifying from '../test/forms/testApiKeysUniquifying'; import formBasedOnWizard from '../test/forms/formBasedOnWizard'; import formWithFormController from '../test/forms/formWithFormController'; +global.requestAnimationFrame = (cb) => cb(); +global.cancelAnimationFrame = () => {}; + describe('WebformBuilder tests', function() { this.retries(3); before((done) => Harness.builderBefore(done)); @@ -283,6 +286,9 @@ describe('Select Component selectData property', () => { }, { label: 'Label 2', value: 'value2', + }, { + label: 'Label 3', + value: 'value3', }]; resolve(values); @@ -384,6 +390,45 @@ describe('Select Component selectData property', () => { }).catch(done); }); + it('Should calculate multiple selectData property for url dataSource', (done) => { + const builder = Harness.getBuilder(); + builder.setForm({}).then(() => { + Harness.buildComponent('select'); + + setTimeout(() => { + const multiple = builder.editForm.getComponent('multiple'); + multiple.setValue(true); + const dataSrc = builder.editForm.getComponent('dataSrc'); + dataSrc.setValue('url'); + const url = builder.editForm.getComponent(['data.url']); + const valueProperty = builder.editForm.getComponent('valueProperty'); + url.setValue('htts//fakeurl.com'); + valueProperty.setValue('value'); + + setTimeout(() => { + const defaultValue = builder.editForm.getComponent('defaultValue'); + defaultValue.setValue(['value1', 'value3']); + defaultValue.updateItems(null, true); + + setTimeout(() => { + assert.deepEqual(builder.editForm.data.selectData, { + value1: { + label: 'Label 1', + }, + value3: { + label: 'Label 3', + }, + }); + Harness.saveComponent(); + setTimeout(() => { + done(); + }, 150); + }, 250); + }, 250); + }, 150); + }).catch(done); + }); + after((done) => { Formio.makeRequest = originalMakeRequest; Harness.builderAfter(done); diff --git a/src/components/select/Select.unit.js b/src/components/select/Select.unit.js index b478b183cc..f0a9d6bd70 100644 --- a/src/components/select/Select.unit.js +++ b/src/components/select/Select.unit.js @@ -32,6 +32,7 @@ import { comp20, comp21, comp22, + comp23, } from './fixtures'; // eslint-disable-next-line max-statements @@ -1042,6 +1043,63 @@ describe('Select Component', () => { }).catch(done); }); + it('Should provide correct metadata.selectData for multiple Select with default value', (done) => { + const form = _.cloneDeep(comp23); + const element = document.createElement('div'); + + Formio.createForm(element, form).then(form => { + const submit = form.getComponent('submit'); + const clickEvent = new Event('click'); + const submitBtn = submit.refs.button; + submitBtn.dispatchEvent(clickEvent); + + setTimeout(()=> { + const metadata = form.submission.metadata.selectData.select; + assert.deepEqual(metadata, { + value1: { + label: 'Label 1', + }, + value3: { + label: 'Label 3', + }, + }); + done(); + }, 200); + }).catch(done); + }); + + it('Should set correct label from metadata for multiple Select with default value', (done) => { + const form = _.cloneDeep(comp23); + const element = document.createElement('div'); + + Formio.createForm(element, form).then(form => { + const select = form.getComponent('select'); + form.submission = { + data: { + select: ['value1', 'value2'], + }, + metadata: { + selectData: { + select: { + value1: { + label: 'Label 1', + }, + value2: { + label: 'Label 2', + }, + }, + }, + }, + }; + + setTimeout(()=> { + assert.equal(select.templateData['value1'].label, 'Label 1'); + assert.equal(select.templateData['value2'].label, 'Label 2'); + done(); + }, 200); + }).catch(done); + }); + it('OnBlur validation should work properly with Select component', function(done) { this.timeout(0); const element = document.createElement('div'); diff --git a/src/components/select/editForm/Select.edit.data.js b/src/components/select/editForm/Select.edit.data.js index e860bf6d46..485cb4bbcf 100644 --- a/src/components/select/editForm/Select.edit.data.js +++ b/src/components/select/editForm/Select.edit.data.js @@ -1,9 +1,9 @@ import _ from 'lodash'; import { eachComponent } from '../../../utils/utils'; -const calculateSelectData = (context) => { +const calculateSingleSelectData = (context, defaultValue) => { const { instance, data } = context; - const rawDefaultValue = instance.downloadedResources.find(resource => _.get(resource, data.valueProperty) === instance.getValue()); + const rawDefaultValue = instance.downloadedResources.find(resource => _.get(resource, data.valueProperty) === defaultValue); const options = { data: {}, noeval: true }; instance.interpolate(data.template, { item: rawDefaultValue, @@ -11,6 +11,21 @@ const calculateSelectData = (context) => { return options.data.item; }; +const calculateSelectData = (context) => { + const { instance } = context; + const defaultValue = instance.getValue(); + if (instance.component.multiple) { + const multiSelectData = {}; + (defaultValue ?? []).forEach((defaultValueItem) => { + multiSelectData[defaultValueItem] = calculateSingleSelectData(context, defaultValueItem); + }); + return multiSelectData; + } + else { + return calculateSingleSelectData(context, defaultValue); + } +}; + const setSelectData = (context) => { // Wait before downloadedResources will be set setTimeout(() => { diff --git a/src/components/select/fixtures/comp22.js b/src/components/select/fixtures/comp22.js index e04a8c8780..54b9e41d04 100644 --- a/src/components/select/fixtures/comp22.js +++ b/src/components/select/fixtures/comp22.js @@ -6,7 +6,7 @@ export default { display: 'form', components: [{ label: 'Select', - widget: 'choicesjs', + widget: 'html5', tableView: true, dataSrc: 'url', data: { diff --git a/src/components/select/fixtures/comp23.js b/src/components/select/fixtures/comp23.js new file mode 100644 index 0000000000..3cfdaed2d2 --- /dev/null +++ b/src/components/select/fixtures/comp23.js @@ -0,0 +1,47 @@ +export default { + title: 'FIO-8281', + name: 'fio8281', + path: 'fio8281', + type: 'form', + display: 'form', + components: [{ + label: 'Select', + widget: 'choicesjs', + tableView: true, + dataSrc: 'url', + data: { + url: 'https://fake_url.com', + headers: [ + { + key: '', + value: '' + }, + ], + }, + multiple: true, + valueProperty: 'value', + validateWhenHidden: false, + key: 'select', + type: 'select', + input: true, + defaultValue: ['value1', 'value3'], + selectValues: 'data', + disableLimit: false, + noRefreshOnScroll: false, + selectData: { + value1: { + label: 'Label 1', + }, + value3: { + label: 'Label 3', + }, + }, + }, { + type: 'button', + label: 'Submit', + key: 'submit', + disableOnInvalid: true, + input: true, + tableView: false, + }], +}; diff --git a/src/components/select/fixtures/index.js b/src/components/select/fixtures/index.js index 4dddb75df9..aad09b2860 100644 --- a/src/components/select/fixtures/index.js +++ b/src/components/select/fixtures/index.js @@ -20,4 +20,5 @@ import comp19 from './comp19'; import comp20 from './comp20'; import comp21 from './comp21'; import comp22 from './comp22'; -export { comp1, comp2, comp4, comp5, comp6, comp7, comp8, comp9, comp10, comp11, comp12, comp13, comp14, comp15, comp16, comp17, comp18, comp19, comp20, comp21, comp22 }; +import comp23 from './comp23'; +export { comp1, comp2, comp4, comp5, comp6, comp7, comp8, comp9, comp10, comp11, comp12, comp13, comp14, comp15, comp16, comp17, comp18, comp19, comp20, comp21, comp22, comp23 };