From c21885d3ac475d237d0b24201574d15d40e9ca38 Mon Sep 17 00:00:00 2001 From: alexandraRamanenka <60643585+alexandraRamanenka@users.noreply.github.com> Date: Mon, 27 May 2024 12:47:04 +0300 Subject: [PATCH] FIO-7195: Fixes an issue where Select, Radio and SelectBoxes components with URL DataSource show values instead of labels in modal preview (#5586) * FIO-7195: Fixes an issue where Select, Radio and SelectBoxes components with URL DataSource show values instead of labels in modal preview * Fixed tests --- src/Webform.unit.js | 64 ++++++++++++++- src/components/radio/Radio.js | 9 ++- src/components/select/Select.js | 5 ++ src/components/selectboxes/SelectBoxes.js | 5 +- test/forms/selectRadioUrlDataSource.js | 95 +++++++++++++++++++++++ 5 files changed, 173 insertions(+), 5 deletions(-) create mode 100644 test/forms/selectRadioUrlDataSource.js diff --git a/src/Webform.unit.js b/src/Webform.unit.js index 53c9ae846b..418181ed71 100644 --- a/src/Webform.unit.js +++ b/src/Webform.unit.js @@ -35,7 +35,7 @@ import { formWithCollapsedPanel, formWithCustomFormatDate, tooltipActivateCheckbox, - formWithObjectValueSelect + formWithObjectValueSelect, } from '../test/formtest'; import UpdateErrorClassesWidgets from '../test/forms/updateErrorClasses-widgets'; import nestedModalWizard from '../test/forms/nestedModalWizard'; @@ -78,7 +78,9 @@ import formWithDeeplyNestedConditionalComps from '../test/forms/formWithDeeplyNe import formWithValidation from '../test/forms/formWithValidation'; import formWithNotAllowedTags from '../test/forms/formWithNotAllowedTags'; import formWithValidateWhenHidden from '../test/forms/formWithValidateWhenHidden'; +import formWithSelectRadioUrlDataSource from '../test/forms/selectRadioUrlDataSource'; const SpySanitize = sinon.spy(FormioUtils, 'sanitize'); + global.requestAnimationFrame = (cb) => cb(); global.cancelAnimationFrame = () => {}; @@ -4847,6 +4849,66 @@ describe('Webform tests', function() { }); }); + it('Should render labels for Select, Radio and selectBoxes components when Data Source is URL', (done) => { + const element = document.createElement('div'); + const form = new Webform(element); + const originalMakeRequest = Formio.makeRequest; + + Formio.makeRequest = function() { + return new Promise(resolve => { + const values = [ + { name : 'Alabama', abbreviation : 'AL' }, + { name : 'Alaska', abbreviation: 'AK' }, + { name: 'American Samoa', abbreviation: 'AS' } + ]; + resolve(values); + }); + }; + + form.setForm(formWithSelectRadioUrlDataSource).then(() => { + const selectBoxes = form.getComponent('selectBoxes'); + const select = form.getComponent('select'); + const radio = form.getComponent('radio'); + + selectBoxes.componentModal.openModal(); + select.componentModal.openModal(); + radio.componentModal.openModal(); + + setTimeout(() => { + form.setSubmission({ + data: { + selectBoxes: { AL: false, AK: true, AS: true }, + select: 'AL', + radio: 'AL', + } + }); + + setTimeout(() => { + selectBoxes.componentModal.closeModal(); + select.componentModal.closeModal(); + radio.componentModal.closeModal(); + + setTimeout(() => { + const previewSelectBoxes = selectBoxes.element.querySelector('[ref="openModal"]'); + const previewSelect = select.element.querySelector('[ref="openModal"]'); + const previewRadio = radio.element.querySelector('[ref="openModal"]'); + + assert.equal(previewSelectBoxes.innerHTML, '\n Alaska, American Samoa\n', 'Should show labels as a selected value' + + ' for SelectBoxes component'); + assert.equal(previewRadio.innerHTML, '\n Alabama\n', 'Should show label as a selected value' + + ' for Radio component'); + assert.equal(previewSelect.innerHTML, '\n Alabama\n', 'Should show label as a selected value' + + ' for Select component'); + + Formio.makeRequest = originalMakeRequest; + done(); + }, 300); + }, 300); + }, 300); + }) + .catch((err) => done(err)); + }); + for (const formTest of FormTests) { const useDoneInsteadOfPromise = formTest.useDone; diff --git a/src/components/radio/Radio.js b/src/components/radio/Radio.js index 34228bda79..985560344a 100644 --- a/src/components/radio/Radio.js +++ b/src/components/radio/Radio.js @@ -261,18 +261,21 @@ export default class RadioComponent extends ListComponent { return false; } - getValueAsString(value) { + getValueAsString(value, options = {}) { if (_.isObject(value)) { value = JSON.stringify(value); } else if (!_.isString(value)) { value = _.toString(value); } - if (this.component.dataSrc !== 'values') { + + const isModalPreviewWithUrlDataSource = options.modalPreview && this.component.dataSrc === 'url'; + if (this.component.dataSrc !== 'values' && !isModalPreviewWithUrlDataSource) { return value; } - const option = _.find(this.component.values, (v) => v.value === value); + const values = isModalPreviewWithUrlDataSource ? this.loadedOptions : this.component.values; + const option = _.find(values, (v) => v.value === value); if (!value) { return _.get(option, 'label', ''); diff --git a/src/components/select/Select.js b/src/components/select/Select.js index 26641a7edb..d17203ddd6 100644 --- a/src/components/select/Select.js +++ b/src/components/select/Select.js @@ -1752,6 +1752,11 @@ export default class SelectComponent extends ListComponent { asString(value, options = {}) { value = value ?? this.getValue(); + + if (options.modalPreview && this.selectData) { + const { label } = this.selectValueAndLabel(value); + return label; + } //need to convert values to strings to be able to compare values with available options that are strings const convertToString = (data, valueProperty) => { if (valueProperty) { diff --git a/src/components/selectboxes/SelectBoxes.js b/src/components/selectboxes/SelectBoxes.js index cbb4583db9..f4a4199c8e 100644 --- a/src/components/selectboxes/SelectBoxes.js +++ b/src/components/selectboxes/SelectBoxes.js @@ -189,12 +189,15 @@ export default class SelectBoxesComponent extends RadioComponent { return changed; } - getValueAsString(value) { + getValueAsString(value, options = {}) { if (!value) { return ''; } if (this.isSelectURL) { + if (options.modalPreview && this.loadedOptions) { + return this.loadedOptions.filter((option) => value[option.value]).map((option) => option.label).join(', '); + } return _(value).pickBy((val) => val).keys().join(', '); } return _(this.component.values || []) diff --git a/test/forms/selectRadioUrlDataSource.js b/test/forms/selectRadioUrlDataSource.js new file mode 100644 index 0000000000..512d963d5f --- /dev/null +++ b/test/forms/selectRadioUrlDataSource.js @@ -0,0 +1,95 @@ +export default { + type: 'form', + display: 'form', + components: [ + { + label: 'Select Boxes - URL', + optionsLabelPosition: 'right', + tableView: true, + modalEdit: true, + dataSrc: 'url', + values: [ + { + label: '', + value: '', + shortcut: '', + }, + ], + valueProperty: 'abbreviation', + key: 'selectBoxes', + type: 'selectboxes', + data: { + url: 'https://gists.rawgit.com/mshafrir/2646763/raw/states_titlecase.json', + headers: [ + { + key: '', + value: '', + }, + ], + }, + template: '{{ item.name }}', + input: true, + inputType: 'checkbox', + }, + { + label: 'Radio', + optionsLabelPosition: 'right', + inline: false, + tableView: true, + modalEdit: true, + dataSrc: 'url', + values: [ + { + label: '', + value: '', + shortcut: '', + }, + ], + valueProperty: 'abbreviation', + key: 'radio', + type: 'radio', + data: { + url: 'https://gists.rawgit.com/mshafrir/2646763/raw/states_titlecase.json', + headers: [ + { + key: '', + value: '', + }, + ], + }, + template: '{{ item.name }}', + input: true, + }, + { + label: 'Select', + widget: 'choicesjs', + tableView: true, + modalEdit: true, + dataSrc: 'url', + data: { + url: 'https://gists.rawgit.com/mshafrir/2646763/raw/states_titlecase.json', + headers: [ + { + key: '', + value: '', + }, + ], + }, + valueProperty: 'abbreviation', + template: '{{ item.name }}', + key: 'select', + type: 'select', + disableLimit: false, + noRefreshOnScroll: false, + input: true, + }, + { + type: 'button', + label: 'Submit', + key: 'submit', + disableOnInvalid: true, + input: true, + tableView: false, + }, + ], +};