diff --git a/app/client/src/widgets/SelectWidget/widget/derived.js b/app/client/src/widgets/SelectWidget/widget/derived.js index 30612ed00db4..2642054ca7e2 100644 --- a/app/client/src/widgets/SelectWidget/widget/derived.js +++ b/app/client/src/widgets/SelectWidget/widget/derived.js @@ -5,16 +5,50 @@ export default { values = [], sourceData = props.sourceData || []; + const processOptionArray = (optionArray, sourceData) => { + if (!sourceData.length) return []; + + const allEqual = optionArray.every((item, _, arr) => item === arr[0]); + const keyExistsInSource = optionArray[0] in sourceData[0]; + + return allEqual && keyExistsInSource + ? sourceData.map((d) => d[optionArray[0]]) + : optionArray; + }; + + /** + * SourceData: + * [{ + * "name": "Blue", + * "code": "name" + * },{ + * "name": "Green", + * "code": "name" + * },{ + * "name": "Red", + * "code": "name" + * }] + * The `Label key` in UI can take following values: + * 1. Normal string, without any quotes. e.g `name` + * This can be assumed as a key in each item of sourceData. We search it in each item of sourceData. + * 2. Except this everything comes in `{{}}`. It can have 2 types of values: + * a. Expressions that evaluate to a normal string. e.g `{{(() => `name`)()}}` + * In this case evaluated value will be ['name', 'name', 'name']. + * i. This can be assumed as a key in each item of sourceData. Handled by `allLabelsEqual` check. + * b. Dynamic property accessed via `item` object. e.g `{{item.name}}` + * In this case evaluated value will be actual values form sourceData ['Red', 'Green', 'Blue']. + * Hence we can assume that this array is the labels array. + * */ if (typeof props.optionLabel === "string") { labels = sourceData.map((d) => d[props.optionLabel]); } else if (_.isArray(props.optionLabel)) { - labels = sourceData.map((d, i) => d[props.optionLabel[i]]); + labels = processOptionArray(props.optionLabel, sourceData); } if (typeof props.optionValue === "string") { values = sourceData.map((d) => d[props.optionValue]); } else if (_.isArray(props.optionValue)) { - values = sourceData.map((d, i) => d[props.optionValue[i]]); + values = processOptionArray(props.optionValue, sourceData); } return sourceData.map((d, i) => ({ diff --git a/app/client/src/widgets/SelectWidget/widget/propertyUtils.ts b/app/client/src/widgets/SelectWidget/widget/propertyUtils.ts index 049490662905..ef3d2bf69f72 100644 --- a/app/client/src/widgets/SelectWidget/widget/propertyUtils.ts +++ b/app/client/src/widgets/SelectWidget/widget/propertyUtils.ts @@ -138,6 +138,27 @@ export function labelKeyValidation( messages: [], }; } else if (_.isArray(value)) { + /* + * Here assumption is that if evaluated array is all equal, then it is a key, + * and we can return the parsed value(from source data) as the options. + */ + const areAllValuesEqual = value.every((item, _, arr) => item === arr[0]); + + if ( + areAllValuesEqual && + props.sourceData[0].hasOwnProperty(String(value[0])) + ) { + const parsedValue = props.sourceData.map( + (d: Record) => d[String(value[0])], + ); + + return { + parsed: parsedValue, + isValid: true, + messages: [], + }; + } + const errorIndex = value.findIndex((d) => !_.isString(d)); return { @@ -218,6 +239,27 @@ export function valueKeyValidation( options = sourceData.map((d: Record) => d[value]); } else if (_.isArray(value)) { + /* + * Here assumption is that if evaluated array is all equal, then it is a key, + * and we can return the parsed value(from source data) as the options. + */ + const areAllValuesEqual = value.every((item, _, arr) => item === arr[0]); + + if ( + areAllValuesEqual && + props.sourceData[0].hasOwnProperty(String(value[0])) + ) { + const parsedValue = props.sourceData.map( + (d: Record) => d[String(value[0])], + ); + + return { + parsed: parsedValue, + isValid: true, + messages: [], + }; + } + const errorIndex = value.findIndex( (d) => !(_.isString(d) || (_.isNumber(d) && !_.isNaN(d)) || _.isBoolean(d)),