Skip to content

Commit

Permalink
fix: Enhance SelectWidget label and value handling logic (#38254)
Browse files Browse the repository at this point in the history
  • Loading branch information
mohanarpit authored Dec 19, 2024
2 parents 28a260f + ec457c9 commit 01d3ff5
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 2 deletions.
38 changes: 36 additions & 2 deletions app/client/src/widgets/SelectWidget/widget/derived.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) => ({
Expand Down
42 changes: 42 additions & 0 deletions app/client/src/widgets/SelectWidget/widget/propertyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, unknown>) => d[String(value[0])],
);

return {
parsed: parsedValue,
isValid: true,
messages: [],
};
}

const errorIndex = value.findIndex((d) => !_.isString(d));

return {
Expand Down Expand Up @@ -218,6 +239,27 @@ export function valueKeyValidation(

options = sourceData.map((d: Record<string, unknown>) => 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<string, unknown>) => d[String(value[0])],
);

return {
parsed: parsedValue,
isValid: true,
messages: [],
};
}

const errorIndex = value.findIndex(
(d) =>
!(_.isString(d) || (_.isNumber(d) && !_.isNaN(d)) || _.isBoolean(d)),
Expand Down

0 comments on commit 01d3ff5

Please sign in to comment.