Link Search Menu Expand Document

Object fields

To be able to create inputs for fields in objects, child form are used. You can create child forms using the ObjectField component or useObjectField hook.

This design choice makes complete type checking possible.

Examples

✔️ Object field using ObjectField

function PersonForm() {
    // Info object contains email and age
    const form = useForm({
        name: "John",
        info: { email: "john@example.com", age: 20 }
    });
    return (
        <form
            onSubmit={(ev) => {
                ev.preventDefault();
                console.log("submit", form.values);
            }}
        >
            {/* Input on root form */}
            <Field form={form} type="text" name="name" />
            <ObjectField
                form={form}
                name="info"
                render={(form) => (
                    <>
                        {/* Inputs on child form, use new form provided by the render function of ObjectField */}
                        <Field form={form} type="text" name="email" />
                        <Field form={form} type="number" name="age" />
                    </>
                )}
            />
            <button>Submit</button>
        </form>
    );
}

✔️ useObjectField without seperate component

function PersonForm() {
    // Create root form
    const form = useForm({ name: "John", info: { email: "john@example.com", age: 20 } });
    // Create child form
    const personInfoForm = useObjectField(form, "info");
    return (
        <form
            onSubmit={(ev) => {
                ev.preventDefault();
                console.log("submit", form.values);
            }}
        >
            {/* Use root form */}
            <Field form={form} type="text" name="name" />
            {/* Use child form */}
            <Field form={personInfoForm} type="number" name="age" />
            <Field form={personInfoForm} type="text" name="email" />
            <button>Submit</button>
        </form>
    );
}

✔️ useObjectField with seperate component

interface Person {
    name: string;
    info: PersonInfo;
}

interface PersonInfo {
    email: string;
    age: number;
}

function PersonForm() {
    // Create the root form
    const form = useForm({
        name: "John",
        info: { email: "john@example.com", age: 20 }
    });
    return (
        <form
            onSubmit={(ev) => {
                ev.preventDefault();
                console.log("submit", form.values);
            }}
        >
            <Field form={form} type="text" name="name" />
            {/* Pass form */}
            <PersonInfoForm parent={form} />
            <button>Submit</button>
        </form>
    );
}

function PersonInfoForm(props: { parent: FormState<Person> }) {
    // Create a new child form from the info field
    const form = useObjectField(props.parent, "info");
    return (
        <>
            <Field form={form} type="text" name="email" />
            <Field form={form} type="number" name="age" />
        </>
    );
}

✔️ You can keep nesting children in children in children ….

This is also possible with ObjectField.

function PersonForm() {
    // Create root form
    const form = useForm({
        name: "John",
        info: {
            email: "john@example.com",
            moreInfo: {
                age: 20,
                moreMoreInfo: {
                    birthDate: new Date()
                }
            }
        }
    });
    // Create child form
    const personInfoForm = useObjectField(form, "info");
    // Create child form on child form
    const personMoreInfoForm = useObjectField(personInfoForm, "moreInfo");
    // Create child form on child form
    const personMoreMoreInfoForm = useObjectField(personMoreInfoForm, "moreMoreInfo"); // This is all type-checked!!
    return (
        <form
            onSubmit={(ev) => {
                ev.preventDefault();
                console.log("submit", form.values);
            }}
        >
            <Field form={form} type="text" name="name" />
            <Field form={personInfoForm} type="text" name="email" />
            <Field form={personMoreInfoForm} type="number" name="age" />
            <Field form={personMoreMoreInfoForm} type="date" name="birthDate" />
            <button>Submit</button>
        </form>
    );
}