From c4f958f037680202cd1add66c4923fa0a2e232d8 Mon Sep 17 00:00:00 2001 From: Joshua Gawenda Date: Sun, 7 Apr 2024 20:30:18 +0200 Subject: [PATCH 1/4] fix(form-react): Fix form options not being optional --- docs/reference/react/useForm.md | 2 +- packages/form-react/src/form/form.hooks.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference/react/useForm.md b/docs/reference/react/useForm.md index c3a30c2..75323e8 100644 --- a/docs/reference/react/useForm.md +++ b/docs/reference/react/useForm.md @@ -12,7 +12,7 @@ declare function useForm< TData, TAdapter extends ValidatorAdapter | undefined = undefined, >( - options: FormLogicOptions, + options?: FormLogicOptions, ): FormContextType; ``` diff --git a/packages/form-react/src/form/form.hooks.tsx b/packages/form-react/src/form/form.hooks.tsx index 0539941..646772c 100644 --- a/packages/form-react/src/form/form.hooks.tsx +++ b/packages/form-react/src/form/form.hooks.tsx @@ -22,7 +22,7 @@ export function useForm< TData, TAdapter extends ValidatorAdapter | undefined = undefined, >( - options: FormLogicOptions, + options?: FormLogicOptions, ): FormContextType { // biome-ignore lint/correctness/useExhaustiveDependencies: We only ever want to create a form once const finalForm = React.useMemo(() => { From 719318a7dbd239510a9015cd730707089ec2ced6 Mon Sep 17 00:00:00 2001 From: Joshua Gawenda Date: Sun, 7 Apr 2024 20:31:25 +0200 Subject: [PATCH 2/4] fix(form-core): Fix FormLogic.updateOptions not allowing to delete fields + array items through new default values --- packages/form-core/src/FormLogic.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/form-core/src/FormLogic.ts b/packages/form-core/src/FormLogic.ts index 1de9e22..483c3c3 100644 --- a/packages/form-core/src/FormLogic.ts +++ b/packages/form-core/src/FormLogic.ts @@ -27,7 +27,6 @@ import { isEqualDeep, makeArrayEntry, removeSignalValueAtPath, - removeValueAtPath, setSignalValueAtPath, setSignalValuesFromObject, setValueAtPath, @@ -394,9 +393,9 @@ export class FormLogic< // We do not want to update dirty field values, since we do not want to reset the form, but just override the default values const newDefaultValues = { ...options.defaultValues } for (const dirtyField of dirtyFields) { - removeValueAtPath(newDefaultValues, dirtyField as never) + setValueAtPath(newDefaultValues, dirtyField as never, undefined) } - setSignalValuesFromObject(this._data, newDefaultValues, true) + setSignalValuesFromObject(this._data, newDefaultValues) } /** From 506914b19f2a1e3715ef2f80297da57f12208371 Mon Sep 17 00:00:00 2001 From: Joshua Gawenda Date: Sun, 7 Apr 2024 20:31:43 +0200 Subject: [PATCH 3/4] test(form-core): Test FormLogic.updateOptions should allow to delete fields + array items through new default values --- packages/form-core/src/FormLogic.spec.ts | 65 +++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/packages/form-core/src/FormLogic.spec.ts b/packages/form-core/src/FormLogic.spec.ts index ee0994c..a1b4560 100644 --- a/packages/form-core/src/FormLogic.spec.ts +++ b/packages/form-core/src/FormLogic.spec.ts @@ -42,9 +42,12 @@ const adapter: ValidatorAdapter = { describe('FormLogic', () => { it('should have the correct initial state', () => { const form = new FormLogic() + + expect(form.isMounted.value).toBeFalsy() form.mount() + expect(form.isMounted.value).toBeTruthy() - expect(form.fields.peek().length).toBe(0) + expect(form.fields.value.length).toBe(0) expect(form.data.value).toStrictEqual({}) expect(form.json.value).toStrictEqual({}) @@ -470,6 +473,34 @@ describe('FormLogic', () => { form.updateOptions({ defaultValues: { name: 'another' } }) expect(form.data.value.name.value).toBe('another') }) + it("should be able to remove fields of dynamic objects or items from an array when updating the options", () =>{ + const form = new FormLogic<{ obj: { [key: string]: string }, array: number[] }>({ + defaultValues: { + obj: { + stay: "stay", + go: "go" + }, + array: [1, 2, 3], + }, + }) + form.mount() + + expect(form.json.value).toEqual({ + obj: { + stay: "stay", + go: "go" + }, + array: [1, 2, 3] + }) + form.updateOptions({ defaultValues: { obj: {stay: "stay(changed)", new: "new"}, array: [2] } }) + expect(form.json.value).toEqual({ + obj: { + stay: "stay(changed)", + new: "new" + }, + array: [2] + }) + }) it('should update the data when using the handleChange method', () => { const form = new FormLogic<{ name: string }>() @@ -1804,6 +1835,22 @@ describe('FormLogic', () => { expect(form.data.value.deep.value.new.value).toBe(2) expect(fn).toHaveBeenCalledTimes(1) }) + it("should touch a field when adding a new key to an object if configured", () => { + const form = new FormLogic<{ deep: { [key: string]: number } }>({ + defaultValues: { + deep: { + value: 1, + }, + }, + }) + form.mount() + const field = new FieldLogic(form, 'deep') + field.mount() + + expect(field.isTouched.value).toBe(false) + form.setValueInObject('deep', 'new', 2, { shouldTouch: true }) + expect(field.isTouched.value).toBe(true) + }) it('should update a value in an object that already has the key', () => { const form = new FormLogic<{ deep: { [key: string]: number } }>({ defaultValues: { @@ -1881,6 +1928,22 @@ describe('FormLogic', () => { expect(form.data.value.deep.value.value).toBeUndefined() expect(fn).toHaveBeenCalledTimes(1) }) + it("should touch a field when removing a key from an object if configured", () => { + const form = new FormLogic<{ deep: { value?: number } }>({ + defaultValues: { + deep: { + value: 1, + }, + }, + }) + form.mount() + const field = new FieldLogic(form, 'deep') + field.mount() + + expect(field.isTouched.value).toBe(false) + form.removeValueInObject('deep', 'value', { shouldTouch: true }) + expect(field.isTouched.value).toBe(true) + }) it('should do nothing when trying to remove a key to a value that is not an object or a date', () => { const form = new FormLogic({ defaultValues: { From d75870ed675e25f298a892ed2b4251efa973795d Mon Sep 17 00:00:00 2001 From: Joshua Gawenda Date: Sun, 7 Apr 2024 20:33:34 +0200 Subject: [PATCH 4/4] style: Run linter --- packages/form-core/src/FormLogic.spec.ts | 34 +++++++++++++++--------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/packages/form-core/src/FormLogic.spec.ts b/packages/form-core/src/FormLogic.spec.ts index a1b4560..8a4aba4 100644 --- a/packages/form-core/src/FormLogic.spec.ts +++ b/packages/form-core/src/FormLogic.spec.ts @@ -473,12 +473,15 @@ describe('FormLogic', () => { form.updateOptions({ defaultValues: { name: 'another' } }) expect(form.data.value.name.value).toBe('another') }) - it("should be able to remove fields of dynamic objects or items from an array when updating the options", () =>{ - const form = new FormLogic<{ obj: { [key: string]: string }, array: number[] }>({ + it('should be able to remove fields of dynamic objects or items from an array when updating the options', () => { + const form = new FormLogic<{ + obj: { [key: string]: string } + array: number[] + }>({ defaultValues: { obj: { - stay: "stay", - go: "go" + stay: 'stay', + go: 'go', }, array: [1, 2, 3], }, @@ -487,18 +490,23 @@ describe('FormLogic', () => { expect(form.json.value).toEqual({ obj: { - stay: "stay", - go: "go" + stay: 'stay', + go: 'go', + }, + array: [1, 2, 3], + }) + form.updateOptions({ + defaultValues: { + obj: { stay: 'stay(changed)', new: 'new' }, + array: [2], }, - array: [1, 2, 3] }) - form.updateOptions({ defaultValues: { obj: {stay: "stay(changed)", new: "new"}, array: [2] } }) expect(form.json.value).toEqual({ obj: { - stay: "stay(changed)", - new: "new" + stay: 'stay(changed)', + new: 'new', }, - array: [2] + array: [2], }) }) @@ -1835,7 +1843,7 @@ describe('FormLogic', () => { expect(form.data.value.deep.value.new.value).toBe(2) expect(fn).toHaveBeenCalledTimes(1) }) - it("should touch a field when adding a new key to an object if configured", () => { + it('should touch a field when adding a new key to an object if configured', () => { const form = new FormLogic<{ deep: { [key: string]: number } }>({ defaultValues: { deep: { @@ -1928,7 +1936,7 @@ describe('FormLogic', () => { expect(form.data.value.deep.value.value).toBeUndefined() expect(fn).toHaveBeenCalledTimes(1) }) - it("should touch a field when removing a key from an object if configured", () => { + it('should touch a field when removing a key from an object if configured', () => { const form = new FormLogic<{ deep: { value?: number } }>({ defaultValues: { deep: {