From 234e1608c0ca16dc640c4f371fb07b677ca6976f Mon Sep 17 00:00:00 2001 From: Einar Date: Tue, 1 Sep 2026 11:11:33 +0200 Subject: [PATCH] Fix ObjectContentEditor navigation into objects nested in arrays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Navigating into a property of an object that sits inside an array resolved the value through its parent, and the parent was the array itself. That lookup could not succeed, so the editor silently fell back to rendering the root object while the navigational bar still showed the deeper path — the breadcrumb and the table disagreed with no sign that anything had gone wrong. Navigation paths now address array elements by their index, so a path resolves in a single traversal, a later element navigates to its own content rather than the first one's, and the breadcrumb shows the index it walked through. An unresolvable path returns to the root instead of rendering the wrong data under it. --- .../ObjectContentEditor.tsx | 56 +++++----- ...igating_into_an_object_within_an_array.tsx | 105 ++++++++++++++++++ ...en_addressing_an_array_by_property_name.ts | 18 +++ .../when_array_index_is_out_of_range.ts | 18 +++ .../when_path_traverses_an_array.ts | 18 +++ Source/ObjectContentEditor/objectHelpers.ts | 12 +- .../breadcrumbHelpers.ts | 16 ++- ...when_navigation_path_has_an_array_index.ts | 21 ++++ 8 files changed, 232 insertions(+), 32 deletions(-) create mode 100644 Source/ObjectContentEditor/for_ObjectContentEditor/when_navigating_into_an_object_within_an_array.tsx create mode 100644 Source/ObjectContentEditor/for_getValueAtPath/when_addressing_an_array_by_property_name.ts create mode 100644 Source/ObjectContentEditor/for_getValueAtPath/when_array_index_is_out_of_range.ts create mode 100644 Source/ObjectContentEditor/for_getValueAtPath/when_path_traverses_an_array.ts create mode 100644 Source/ObjectNavigationalBar/for_buildNavigationBreadcrumbs/when_navigation_path_has_an_array_index.ts diff --git a/Source/ObjectContentEditor/ObjectContentEditor.tsx b/Source/ObjectContentEditor/ObjectContentEditor.tsx index 93985683..59b1cbff 100644 --- a/Source/ObjectContentEditor/ObjectContentEditor.tsx +++ b/Source/ObjectContentEditor/ObjectContentEditor.tsx @@ -162,9 +162,9 @@ export const ObjectContentEditor = ({ } }, [validationErrors, editMode, onValidationChange]); - const navigateToProperty = useCallback( - (key: string) => { - setNavigationPath([...navigationPath, key]); + const navigateTo = useCallback( + (segments: string[]) => { + setNavigationPath([...navigationPath, ...segments]); }, [navigationPath], ); @@ -185,28 +185,15 @@ export const ObjectContentEditor = ({ return object; } - const lastKey = navigationPath[navigationPath.length - 1]; - const pathToParent = navigationPath.slice(0, -1); + const value = getValueAtPath(object, navigationPath); + return value !== null && typeof value === 'object' ? value : null; + }, [object, navigationPath]); - const parentValue = - pathToParent.length > 0 ? getValueAtPath(object, pathToParent) : object; - - if ( - parentValue && - typeof parentValue === 'object' && - !Array.isArray(parentValue) - ) { - const value = (parentValue as { [k: string]: Json })[lastKey]; - - if (Array.isArray(value)) { - return value; - } else if (value && typeof value === 'object') { - return value; - } + useEffect(() => { + if (navigationPath.length > 0 && currentData === null) { + setNavigationPath([]); } - - return object; - }, [object, navigationPath, getValueAtPath]); + }, [currentData, navigationPath]); const currentProperties = useMemo(() => { const properties = schema.properties || {}; @@ -447,7 +434,11 @@ export const ObjectContentEditor = ({ ); }; - const renderValue = (value: Json, propertyName: string) => { + const renderValue = ( + value: Json, + propertyName: string, + pathSegments: string[], + ) => { if (value === null || value === undefined) return ''; if (Array.isArray(value)) { @@ -455,7 +446,7 @@ export const ObjectContentEditor = ({