diff --git a/sandbox-app/index.tsx b/sandbox-app/index.tsx
index 06d4365..67bd7be 100644
--- a/sandbox-app/index.tsx
+++ b/sandbox-app/index.tsx
@@ -2,6 +2,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { useForm } from '../src/index';
import { NestedField } from './nested-field';
+import { NestedValidation } from './nested-validation';
import { NullableField } from './nullable-field';
import { ObjectsArray } from './objects-array';
import { SimpleArray } from './simple-array';
@@ -39,6 +40,7 @@ function App(): JSX.Element {
+
>
);
diff --git a/sandbox-app/nested-validation.tsx b/sandbox-app/nested-validation.tsx
new file mode 100644
index 0000000..b69c4e3
--- /dev/null
+++ b/sandbox-app/nested-validation.tsx
@@ -0,0 +1,59 @@
+import React from 'react';
+import { useForm } from '../src';
+import { Input } from './components/Input';
+
+interface Model {
+ address?: {
+ streetName?: string;
+ };
+}
+
+const initialValue: Model = {};
+
+export function NestedValidation(): JSX.Element {
+ const {
+ model,
+ changes,
+ fields,
+ onSubmit,
+ valid,
+ dirty,
+ submissionStatus,
+ reset,
+ } = useForm({
+ model: initialValue,
+ onSubmit: async ({ model }) => {
+ // eslint-disable-next-line no-console
+ console.log(model);
+ },
+ validations: {
+ address: {
+ streetName: 'required',
+ },
+ },
+ });
+
+ return (
+ <>
+
Nested Field
+
+ Model
+
+ {JSON.stringify({ model, valid, dirty, submissionStatus }, null, 2)}
+
+ Changes
+ {JSON.stringify({ changes }, null, 2)}
+ Back
+ >
+ );
+}
diff --git a/src/field.ts b/src/field.ts
index cb80872..47ae164 100644
--- a/src/field.ts
+++ b/src/field.ts
@@ -103,7 +103,7 @@ export class FieldImplementation
get fields(): MappedFields {
if (!this.value) {
this.value = {} as T;
- this.#onUpdate();
+ this.#onUpdate?.();
}
const handler = {
get: (target: MappedFields, key: string) => {
diff --git a/src/form.spec.ts b/src/form.spec.ts
index d8f1b63..3ac1ea6 100644
--- a/src/form.spec.ts
+++ b/src/form.spec.ts
@@ -662,6 +662,24 @@ describe(Form, () => {
expect(emails.dirty).toBeTruthy();
expect(form.dirty).toBeTruthy();
});
+ it('handles nested validation', () => {
+ const form = createForm({
+ value: {
+ address: {
+ streetName: '',
+ },
+ },
+ validations: {
+ address: {
+ streetName: 'required',
+ },
+ },
+ });
+ expect(form.fields.address.fields.streetName.errors).toHaveLength(1);
+ expect(form.fields.address.fields.streetName.errors[0]).toBe(
+ 'required-field'
+ );
+ });
});
});