diff --git a/src/components/select/Select.js b/src/components/select/Select.js index 0fc6ea116e..50360076f4 100644 --- a/src/components/select/Select.js +++ b/src/components/select/Select.js @@ -253,8 +253,12 @@ export default class SelectComponent extends ListComponent { return super.shouldLoad; } + get selectMetadata() { + return super.selectData; + } + get selectData() { - return this.component.selectData || super.selectData; + return this.component.selectData || this.selectMetadata; } isEntireObjectDisplay() { @@ -1368,7 +1372,7 @@ export default class SelectComponent extends ListComponent { return done; } - normalizeSingleValue(value, retainObject) { + normalizeSingleValue(value) { if (_.isNil(value)) { return; } @@ -1377,35 +1381,6 @@ export default class SelectComponent extends ListComponent { if (valueIsObject && Object.keys(value).length === 0) { return value; } - // Check to see if we need to save off the template data into our metadata. - if (retainObject) { - const templateValue = this.component.reference && value?._id ? value._id.toString() : value; - const shouldSaveData = !valueIsObject || this.component.reference; - if (templateValue && shouldSaveData && (this.templateData && this.templateData[templateValue]) && this.root?.submission) { - const submission = this.root.submission; - if (!submission.metadata) { - submission.metadata = {}; - } - if (!submission.metadata.selectData) { - submission.metadata.selectData = {}; - } - - let templateData = this.templateData[templateValue]; - if (this.component.multiple) { - templateData = {}; - const dataValue = this.dataValue; - if (dataValue && _.isArray(dataValue) && dataValue.length) { - dataValue.forEach((dataValueItem) => { - const dataValueItemValue = this.component.reference ? dataValueItem._id.toString() : dataValueItem; - templateData[dataValueItemValue] = this.templateData[dataValueItemValue]; - }); - } - templateData[value] = this.templateData[value]; - } - - _.set(submission.metadata.selectData, this.path, templateData); - } - } const dataType = this.component.dataType || 'auto'; const normalize = { @@ -1472,18 +1447,69 @@ export default class SelectComponent extends ListComponent { */ normalizeValue(value) { if (this.component.multiple && Array.isArray(value)) { - return value.map((singleValue) => this.normalizeSingleValue(singleValue, true)); + return value.map((singleValue) => this.normalizeSingleValue(singleValue)); + } + + return super.normalizeValue(this.normalizeSingleValue(value)); + } + + setMetadata(value) { + if (_.isNil(value)) { + return; + } + const valueIsObject = _.isObject(value); + //check if value equals to default emptyValue + if (valueIsObject && Object.keys(value).length === 0) { + return value; } + // Check to see if we need to save off the template data into our metadata. + const templateValue = this.component.reference && value?._id ? value._id.toString() : value; + const shouldSaveData = !valueIsObject || this.component.reference; + if (templateValue && shouldSaveData && this.templateData && this.templateData[templateValue] && this.root?.submission) { + const submission = this.root.submission; + if (!submission.metadata) { + submission.metadata = {}; + } + if (!submission.metadata.selectData) { + submission.metadata.selectData = {}; + } + + let templateData = this.templateData[templateValue]; + if (this.component.multiple) { + templateData = {}; + const dataValue = this.dataValue; + if (dataValue && _.isArray(dataValue) && dataValue.length) { + dataValue.forEach((dataValueItem) => { + const dataValueItemValue = this.component.reference ? dataValueItem._id.toString() : dataValueItem; + templateData[dataValueItemValue] = this.templateData[dataValueItemValue]; + }); + } + templateData[value] = this.templateData[value]; + } - return super.normalizeValue(this.normalizeSingleValue(value, true)); + _.set(submission.metadata.selectData, this.path, templateData); + } + } + + updateValue(value, flags) { + const changed = super.updateValue(value, flags); + if (changed || !this.selectMetadata) { + if (this.component.multiple && Array.isArray(this.dataValue)) { + this.dataValue.forEach(singleValue => this.setMetadata(singleValue)); + } + else { + this.setMetadata(this.dataValue); + } + } + return changed; } setValue(value, flags = {}) { const previousValue = this.dataValue; + const changed = this.updateValue(value, flags); if (this.component.widget === 'html5' && (_.isEqual(value, previousValue) || _.isEqual(previousValue, {}) && _.isEqual(flags, {})) && !flags.fromSubmission ) { return false; } - const changed = this.updateValue(value, flags); value = this.dataValue; const hasPreviousValue = !this.isEmpty(previousValue); const hasValue = !this.isEmpty(value); @@ -1612,7 +1638,7 @@ export default class SelectComponent extends ListComponent { if (values) { if (_.isObject(value)) { const compareComplexValues = (optionValue) => { - const normalizedOptionValue = this.normalizeSingleValue(optionValue, true); + const normalizedOptionValue = this.normalizeSingleValue(optionValue); if (!_.isObject(normalizedOptionValue)) { return false; diff --git a/src/components/select/Select.unit.js b/src/components/select/Select.unit.js index e0975133ef..c72c5694cc 100644 --- a/src/components/select/Select.unit.js +++ b/src/components/select/Select.unit.js @@ -31,6 +31,7 @@ import { comp19, comp20, comp21, + comp22, } from './fixtures'; // eslint-disable-next-line max-statements @@ -977,6 +978,43 @@ describe('Select Component', () => { }).catch(done); }); + it('Should provide correct metadata.selectData for HTML5 Select with default value', (done) => { + const form = _.cloneDeep(comp22); + 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.equal(metadata.label, 'Label 1'); + done(); + }, 200); + }).catch(done); + }); + + it('Should provide correct metadata.selectData for ChoicesJS Select with default value', (done) => { + const form = _.cloneDeep(comp22); + form.components[0].widget='choicesjs'; + 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.equal(metadata.label, 'Label 1'); + 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/fixtures/comp22.js b/src/components/select/fixtures/comp22.js new file mode 100644 index 0000000000..cdd0787a5e --- /dev/null +++ b/src/components/select/fixtures/comp22.js @@ -0,0 +1,41 @@ +export default { + title: 'FIO-8091', + name: 'fio8091', + path: 'fio8091', + type: 'form', + display: 'form', + components: [{ + label: 'Select', + widget: 'choicesjs', + tableView: true, + dataSrc: 'url', + data: { + url: 'https://fake_url', + headers: [ + { + key: '', + value: '' + }, + ], + }, + valueProperty: 'value', + validateWhenHidden: false, + key: 'select', + type: 'select', + input: true, + defaultValue: 'value1', + selectValues: 'data', + disableLimit: false, + noRefreshOnScroll: false, + selectData: { + label: 'Label 1' + }, + }, { + 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 7e0e7d9307..4dddb75df9 100644 --- a/src/components/select/fixtures/index.js +++ b/src/components/select/fixtures/index.js @@ -19,4 +19,5 @@ import comp18 from './comp18'; import comp19 from './comp19'; import comp20 from './comp20'; import comp21 from './comp21'; -export { comp1, comp2, comp4, comp5, comp6, comp7, comp8, comp9, comp10, comp11, comp12, comp13, comp14, comp15, comp16, comp17, comp18, comp19, comp20, 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 };