Form schema
Condition
Learn how the condition element is used in the schema.
Usage
The condition element is used to define a condition.
To understand how it is used let's look at this example.
import type { Schema, Form, Return, Cond } from "@formity/react";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import {
Step,
Layout,
Row,
TextField,
NumberField,
YesNo,
MultiSelect,
Listbox,
NextButton,
BackButton,
} from "./components";
import { MultiStep } from "./multi-step";
export type Values = [
Form<{ name: string; surname: string; age: number }>,
Form<{ softwareDeveloper: boolean }>,
Cond<{
then: [
Form<{ languages: string[] }>,
Return<{
name: string;
surname: string;
age: number;
softwareDeveloper: true;
languages: string[];
}>,
];
else: [
Form<{ interested: string }>,
Return<{
name: string;
surname: string;
age: number;
softwareDeveloper: false;
interested: string;
}>,
];
}>,
];
export const schema: Schema<Values> = [
{
form: {
values: () => ({
name: ["", []],
surname: ["", []],
age: [20, []],
}),
render: ({ values, onNext, onBack }) => (
<MultiStep onNext={onNext} onBack={onBack}>
<Step
key="main"
defaultValues={values}
resolver={zodResolver(
z.object({
name: z
.string()
.min(1, { message: "Required" })
.max(20, { message: "Must be at most 20 characters" }),
surname: z
.string()
.min(1, { message: "Required" })
.max(20, { message: "Must be at most 20 characters" }),
age: z
.number()
.min(18, { message: "Minimum of 18 years old" })
.max(99, { message: "Maximum of 99 years old" }),
}),
)}
>
<Layout
heading="Tell us about yourself"
description="We would want to know about you"
fields={[
<Row
key="name-surname"
items={[
<TextField key="name" name="name" label="Name" />,
<TextField key="surname" name="surname" label="Surname" />,
]}
/>,
<NumberField key="age" name="age" label="Age" />,
]}
button={<NextButton>Next</NextButton>}
/>
</Step>
</MultiStep>
),
},
},
{
form: {
values: () => ({
softwareDeveloper: [true, []],
}),
render: ({ values, onNext, onBack }) => (
<MultiStep onNext={onNext} onBack={onBack}>
<Step
key="softwareDeveloper"
defaultValues={values}
resolver={zodResolver(
z.object({
softwareDeveloper: z.boolean(),
}),
)}
>
<Layout
heading="Are you a software developer?"
description="We would like to know if you are a software developer"
fields={[
<YesNo
key="softwareDeveloper"
name="softwareDeveloper"
label="Software Developer"
/>,
]}
button={<NextButton>Next</NextButton>}
back={<BackButton />}
/>
</Step>
</MultiStep>
),
},
},
{
cond: {
if: ({ softwareDeveloper }) => softwareDeveloper,
then: [
{
form: {
values: () => ({
languages: [[], []],
}),
render: ({ values, onNext, onBack }) => (
<MultiStep onNext={onNext} onBack={onBack}>
<Step
key="languages"
defaultValues={values}
resolver={zodResolver(
z.object({
languages: z.array(z.string()),
}),
)}
>
<Layout
heading="What are your favourite programming languages?"
description="We would like to know which of the following programming languages you like the most"
fields={[
<MultiSelect
key="languages"
name="languages"
label="Languages"
options={[
{ value: "javascript", label: "JavaScript" },
{ value: "python", label: "Python" },
{ value: "go", label: "Go" },
]}
direction="y"
/>,
]}
button={<NextButton>Next</NextButton>}
back={<BackButton />}
/>
</Step>
</MultiStep>
),
},
},
{
return: ({ name, surname, age, languages }) => ({
name,
surname,
age,
softwareDeveloper: true,
languages,
}),
},
],
else: [
{
form: {
values: () => ({
interested: ["maybe", []],
}),
render: ({ values, onNext, onBack }) => (
<MultiStep onNext={onNext} onBack={onBack}>
<Step
key="interested"
defaultValues={values}
resolver={zodResolver(
z.object({
interested: z.string(),
}),
)}
>
<Layout
heading="Would you be interested in learning how to code?"
description="Having coding skills can be very beneficial"
fields={[
<Listbox
key="interested"
name="interested"
label="Interested"
options={[
{
value: "maybe",
label: "Maybe in another time.",
},
{
value: "yes",
label: "Yes, that sounds good.",
},
{
value: "no",
label: "No, it is not for me.",
},
]}
/>,
]}
button={<NextButton>Next</NextButton>}
back={<BackButton />}
/>
</Step>
</MultiStep>
),
},
},
{
return: ({ name, surname, age, interested }) => ({
name,
surname,
age,
softwareDeveloper: false,
interested,
}),
},
],
},
},
];
We need to use the Cond
type with the corresponding types.
export type Values = [
// ...
Cond<{
then: [
Form<{ languages: string[] }>,
Return<{
name: string;
surname: string;
age: number;
softwareDeveloper: true;
languages: string[];
}>,
];
else: [
Form<{ interested: string }>,
Return<{
name: string;
surname: string;
age: number;
softwareDeveloper: false;
interested: string;
}>,
];
}>,
];
Then, in the schema we need to create an object with the following structure.
export const schema: Schema<Values> = [
// ...
{
cond: {
if: ({ softwareDeveloper }) => softwareDeveloper,
then: [
{
form: {
values: () => ({
languages: [[], []],
}),
render: ({ values, onNext, onBack }) => (
<MultiStep onNext={onNext} onBack={onBack}>
<Step
key="languages"
defaultValues={values}
resolver={zodResolver(
z.object({
languages: z.array(z.string()),
}),
)}
>
<Layout
heading="What are your favourite programming languages?"
description="We would like to know which of the following programming languages you like the most"
fields={[
<MultiSelect
key="languages"
name="languages"
label="Languages"
options={[
{ value: "javascript", label: "JavaScript" },
{ value: "python", label: "Python" },
{ value: "go", label: "Go" },
]}
direction="y"
/>,
]}
button={<NextButton>Next</NextButton>}
back={<BackButton />}
/>
</Step>
</MultiStep>
),
},
},
{
return: ({ name, surname, age, languages }) => ({
name,
surname,
age,
softwareDeveloper: true,
languages,
}),
},
],
else: [
{
form: {
values: () => ({
interested: ["maybe", []],
}),
render: ({ values, onNext, onBack }) => (
<MultiStep onNext={onNext} onBack={onBack}>
<Step
key="interested"
defaultValues={values}
resolver={zodResolver(
z.object({
interested: z.string(),
}),
)}
>
<Layout
heading="Would you be interested in learning how to code?"
description="Having coding skills can be very beneficial"
fields={[
<Listbox
key="interested"
name="interested"
label="Interested"
options={[
{
value: "maybe",
label: "Maybe in another time.",
},
{
value: "yes",
label: "Yes, that sounds good.",
},
{
value: "no",
label: "No, it is not for me.",
},
]}
/>,
]}
button={<NextButton>Next</NextButton>}
back={<BackButton />}
/>
</Step>
</MultiStep>
),
},
},
{
return: ({ name, surname, age, interested }) => ({
name,
surname,
age,
softwareDeveloper: false,
interested,
}),
},
],
},
},
];
The if
property is a function that takes the input values and returns a boolean value. If it is true, the elements in then
are used. Otherwise, the elements in else
are used.