From 5355b8652df8ca9b00827439228605caac81c979 Mon Sep 17 00:00:00 2001 From: Anton Platonov Date: Thu, 5 Dec 2024 17:17:27 +0200 Subject: [PATCH] fix(form): initialize arrays when receiving items Fixes #2949 --- packages/ts/lit-form/src/BinderNode.ts | 4 ++-- packages/ts/lit-form/test/Binder.test.ts | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/ts/lit-form/src/BinderNode.ts b/packages/ts/lit-form/src/BinderNode.ts index cc3776ebb1..c96c64de71 100644 --- a/packages/ts/lit-form/src/BinderNode.ts +++ b/packages/ts/lit-form/src/BinderNode.ts @@ -267,7 +267,7 @@ export class BinderNode extends EventTa } set value(value: Value | undefined) { - this.initializeValue(); + this.initializeValue(true); this.#setValueState(value, undefined); } @@ -500,7 +500,7 @@ export class BinderNode extends EventTa : undefined; const defaultValue: Value | undefined = this.parent - ? (this.parent.defaultValue as { readonly [key in typeof key]: Value })[this.model[_key]] + ? (this.parent.defaultValue as { readonly [key in typeof key]: Value } | undefined)[this.model[_key]] : undefined; if (value === undefined) { diff --git a/packages/ts/lit-form/test/Binder.test.ts b/packages/ts/lit-form/test/Binder.test.ts index bdcdec6aa8..e22295658e 100644 --- a/packages/ts/lit-form/test/Binder.test.ts +++ b/packages/ts/lit-form/test/Binder.test.ts @@ -5,7 +5,7 @@ import { customElement } from 'lit/decorators.js'; import sinon from 'sinon'; import sinonChai from 'sinon-chai'; // API to test -import { Binder, type BinderConfiguration } from '../src/index.js'; +import { Binder, type BinderConfiguration, m } from '../src/index.js'; import { type Employee, EmployeeModel, @@ -302,6 +302,21 @@ describe('@vaadin/hilla-lit-form', () => { assert.isTrue('supervisor' in binder.value); }); + it('should support optional array', async () => { + let arrayBinderNode = binder.for(binder.model.colleagues); + assert.isUndefined(arrayBinderNode.value); + assert.isUndefined(arrayBinderNode.defaultValue); + + arrayBinderNode.value = [EmployeeModel.createEmptyValue()]; + const [itemModel] = m.items(arrayBinderNode.model); + assert.deepEqual(binder.for(itemModel).value, expectedEmptyEmployee); + assert.deepEqual(arrayBinderNode.defaultValue, []); + assert.isTrue(arrayBinderNode.dirty); + + await binder.validate(); + assert.isFalse(binder.invalid); + }); + it('should initialize parent optional on child binderNode access', () => { binder.for(binder.model.supervisor.supervisor);