fix: Enhance SelectWidget label and value handling logic (#38254)

This commit is contained in:
Rahul Barwal 2024-12-19 16:08:20 +05:30 committed by GitHub
parent d9b1729ce3
commit 97050485c7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 78 additions and 2 deletions

View File

@ -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) => ({

View File

@ -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 {
@ -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)),