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,
+ },
+ ],
+};