Enhance ObjectSelect Component with Improved Value Handling and Synchronization
- Introduced utility functions to standardize value conversion and retrieval, improving consistency in value handling. - Enhanced synchronization of external values with internal state, ensuring accurate representation of selected items. - Improved selection change handling to prevent unnecessary updates when no valid selection is made. - Refactored tree selection logic for better clarity and maintainability, ensuring robust handling of both single and multiple selections.
This commit is contained in:
parent
a1697fe0fd
commit
8bb8d417f7
@ -25,6 +25,14 @@ const areValuesEqual = (v1, v2) => {
|
|||||||
return String(id1) === String(id2)
|
return String(id1) === String(id2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const toSelectValue = (id) => {
|
||||||
|
if (id == null || id === '') return null
|
||||||
|
return String(id).toLowerCase()
|
||||||
|
}
|
||||||
|
|
||||||
|
const getValueId = (item) =>
|
||||||
|
item && typeof item === 'object' ? item._id : item
|
||||||
|
|
||||||
const getFirstSelectableLeaf = (nodes) => {
|
const getFirstSelectableLeaf = (nodes) => {
|
||||||
if (!Array.isArray(nodes)) return null
|
if (!Array.isArray(nodes)) return null
|
||||||
for (const node of nodes) {
|
for (const node of nodes) {
|
||||||
@ -69,6 +77,23 @@ const isValueInTree = (nodes, id) => {
|
|||||||
return findTreeNodeByValue(nodes, id) != null
|
return findTreeNodeByValue(nodes, id) != null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getSelectValueFromExternal = (externalValue, multiple, nodes) => {
|
||||||
|
if (externalValue == null || !Array.isArray(nodes) || nodes.length === 0) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multiple) {
|
||||||
|
const values = Array.isArray(externalValue) ? externalValue : []
|
||||||
|
const ids = values
|
||||||
|
.map((item) => toSelectValue(getValueId(item)))
|
||||||
|
.filter((id) => id != null && isValueInTree(nodes, id))
|
||||||
|
return ids
|
||||||
|
}
|
||||||
|
|
||||||
|
const node = findTreeNodeByValue(nodes, getValueId(externalValue))
|
||||||
|
return node?.value
|
||||||
|
}
|
||||||
|
|
||||||
const isExternalValueMissing = (
|
const isExternalValueMissing = (
|
||||||
externalValue,
|
externalValue,
|
||||||
multiple,
|
multiple,
|
||||||
@ -528,9 +553,27 @@ const ObjectSelect = ({
|
|||||||
setObjectList(objects)
|
setObjectList(objects)
|
||||||
setTreeData(treeNodes)
|
setTreeData(treeNodes)
|
||||||
treeDataRef.current = treeNodes
|
treeDataRef.current = treeNodes
|
||||||
|
|
||||||
|
const syncedValue = getSelectValueFromExternal(
|
||||||
|
valueRef.current,
|
||||||
|
multiple,
|
||||||
|
treeNodes
|
||||||
|
)
|
||||||
|
if (multiple) {
|
||||||
|
if (Array.isArray(syncedValue) && syncedValue.length > 0) {
|
||||||
|
setTreeSelectValue(syncedValue)
|
||||||
|
setValueNotFound(false)
|
||||||
|
clearedMissingValueRef.current = false
|
||||||
|
}
|
||||||
|
} else if (syncedValue != null) {
|
||||||
|
setTreeSelectValue(syncedValue)
|
||||||
|
setValueNotFound(false)
|
||||||
|
clearedMissingValueRef.current = false
|
||||||
|
}
|
||||||
|
|
||||||
return { treeNodes, objects }
|
return { treeNodes, objects }
|
||||||
},
|
},
|
||||||
[buildTreeData]
|
[buildTreeData, multiple]
|
||||||
)
|
)
|
||||||
|
|
||||||
const buildFilterFromNode = useCallback(
|
const buildFilterFromNode = useCallback(
|
||||||
@ -633,6 +676,17 @@ const ObjectSelect = ({
|
|||||||
|
|
||||||
const onTreeSelectChange = useCallback(
|
const onTreeSelectChange = useCallback(
|
||||||
(value) => {
|
(value) => {
|
||||||
|
const isEmptySelection = multiple
|
||||||
|
? !Array.isArray(value) || value.length === 0
|
||||||
|
: value == null || value === ''
|
||||||
|
if (
|
||||||
|
isEmptySelection &&
|
||||||
|
treeDataRef.current.length === 0 &&
|
||||||
|
valueRef.current != null
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
setValueNotFound(false)
|
setValueNotFound(false)
|
||||||
clearedMissingValueRef.current = false
|
clearedMissingValueRef.current = false
|
||||||
// Mark this as an internal change
|
// Mark this as an internal change
|
||||||
@ -827,7 +881,7 @@ const ObjectSelect = ({
|
|||||||
setExpandedKeys([...new Set(pathKeys)])
|
setExpandedKeys([...new Set(pathKeys)])
|
||||||
setTreeSelectValue(
|
setTreeSelectValue(
|
||||||
value
|
value
|
||||||
.map((item) => (item && typeof item === 'object' ? item._id : item))
|
.map((item) => toSelectValue(getValueId(item)))
|
||||||
.filter((id) => id != null)
|
.filter((id) => id != null)
|
||||||
)
|
)
|
||||||
setInitialized(true)
|
setInitialized(true)
|
||||||
@ -880,7 +934,7 @@ const ObjectSelect = ({
|
|||||||
setExpandedKeys(pathKeys)
|
setExpandedKeys(pathKeys)
|
||||||
// Fetch with the new filter
|
// Fetch with the new filter
|
||||||
handleFetchObjectsProperties(valueFilter)
|
handleFetchObjectsProperties(valueFilter)
|
||||||
setTreeSelectValue(valueRef.current._id)
|
setTreeSelectValue(toSelectValue(valueRef.current._id))
|
||||||
setInitialized(true)
|
setInitialized(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -905,7 +959,13 @@ const ObjectSelect = ({
|
|||||||
setInitialized(true)
|
setInitialized(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handleValue()
|
const timeoutId = setTimeout(() => {
|
||||||
|
handleValue()
|
||||||
|
}, 10)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearTimeout(timeoutId)
|
||||||
|
}
|
||||||
}, [
|
}, [
|
||||||
value,
|
value,
|
||||||
filter,
|
filter,
|
||||||
@ -940,6 +1000,7 @@ const ObjectSelect = ({
|
|||||||
setTreeVersion((v) => v + 1)
|
setTreeVersion((v) => v + 1)
|
||||||
setExpandedKeys([])
|
setExpandedKeys([])
|
||||||
setInitialized(false)
|
setInitialized(false)
|
||||||
|
valueRef.current = null
|
||||||
onTreeSelectChange(null)
|
onTreeSelectChange(null)
|
||||||
setTreeSelectValue(null)
|
setTreeSelectValue(null)
|
||||||
setInitialLoading(true)
|
setInitialLoading(true)
|
||||||
@ -963,7 +1024,12 @@ const ObjectSelect = ({
|
|||||||
if (changeSource == 'external') {
|
if (changeSource == 'external') {
|
||||||
setObjectPropertiesTree({})
|
setObjectPropertiesTree({})
|
||||||
setTreeData([])
|
setTreeData([])
|
||||||
|
treeDataRef.current = []
|
||||||
setInitialized(false)
|
setInitialized(false)
|
||||||
|
setInitialLoading(true)
|
||||||
|
valueRef.current = null
|
||||||
|
clearedMissingValueRef.current = false
|
||||||
|
setValueNotFound(false)
|
||||||
prevValuesRef.current = { type, masterFilter }
|
prevValuesRef.current = { type, masterFilter }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user