From c0d5a34457776b60e4317e65ed325ad98a5789e5 Mon Sep 17 00:00:00 2001 From: Lucas Koehler Date: Thu, 24 Sep 2026 16:32:18 +0000 Subject: [PATCH 1/9] fix(angular-material): don't mutate the given ui schema in array layouts ArrayLayoutRenderer#getProps was called from the template, i.e. on every change detection cycle, and called setReadonly/unsetReadonly on the result of findUISchema. For an inline options.detail - or a ui schema from the registry - findUISchema hands back the very object the user passed in, and setReadonly/unsetReadonly modify it in place. While the array is empty getProps is never called, so the first "add" is the first time options.readonly is written into the user's ui schema. Ancestor layouts track their children by `path + JSON.stringify(uischema)`, so that write changes the track key of the whole branch, NgForOf destroys and re-creates the embedded view, and any state below it is lost. For a Categorization that means the selected tab jumps back to the first one - only on the first "add", because later ones write the same value. findUISchema is now called from mapAdditionalProps instead of the template, its result is copied before setting the readonly option, and it is only recalculated when one of its inputs actually changed. The items' props are precalculated as well, so that the template no longer hands a new object to jsonforms-outlet on every change detection cycle - each of those made the outlet deep clone the whole form state, once per item. Also adds an example reproducing the issue. Fixes #2343 --- .../library/layouts/array-layout.renderer.ts | 105 +++++++-- .../angular-material/src/library/util/deps.ts | 40 ++++ .../test/array-layout.spec.ts | 206 +++++++++++++++++- packages/angular-material/test/common/util.ts | 8 +- .../examples/src/examples/categorization.ts | 65 ++++++ 5 files changed, 392 insertions(+), 32 deletions(-) create mode 100644 packages/angular-material/src/library/util/deps.ts diff --git a/packages/angular-material/src/library/layouts/array-layout.renderer.ts b/packages/angular-material/src/library/layouts/array-layout.renderer.ts index 24626dc7a5..3d5d34092a 100644 --- a/packages/angular-material/src/library/layouts/array-layout.renderer.ts +++ b/packages/angular-material/src/library/layouts/array-layout.renderer.ts @@ -52,6 +52,8 @@ import { UISchemaTester, unsetReadonly, } from '@jsonforms/core'; +import cloneDeep from 'lodash/cloneDeep'; +import { depsChanged } from '../util/deps'; @Component({ selector: 'app-array-layout-renderer', @@ -84,7 +86,7 @@ import {

{{ translations.noDataMessage }}

- +