Form flow
Condition
Learn how the condition element is used in the flow.
Usage
The condition element is used to define a condition.
To understand how it is used let's look at this example.
import { useCallback, useState } from "react";
import {
Formity,
type s,
type Flow,
type OnReturn,
type ReturnOutput,
} from "@formity/react";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { Form } from "./components/form";
import { Output } from "./components/output";
type Schema = {
render: React.ReactNode;
struct: [
s.Form<{ working: string }>,
s.Variables<{ company: string | null }>,
s.Condition<{
then: [s.Form<{ company: string }>];
else: [];
}>,
s.Form<{ study: string }>,
s.Return<{
working: string;
company: string | null;
study: string;
}>,
];
inputs: Record<never, never>;
params: Record<never, never>;
};
const flow: Flow<Schema> = [
{
form: {
fields: () => ({
working: ["yes", []],
}),
render: ({ fields, onBack, onNext }) => (
<Form
key="working"
defaultValues={fields}
resolver={zodResolver(
z.object({
working: z.string(),
}),
)}
heading="Are you working?"
content={[
{
type: "select",
name: "working",
label: "Working",
placeholder: "Select an option",
options: [
{ value: "yes", label: "Yes" },
{ value: "no", label: "No" },
],
},
]}
buttons={{
back: null,
next: "Next",
}}
onBack={onBack}
onNext={onNext}
/>
),
},
},
{
variables: () => ({
company: null,
}),
},
{
condition: {
if: ({ working }) => working === "yes",
then: [
{
form: {
fields: () => ({
company: ["", []],
}),
render: ({ fields, onBack, onNext }) => (
<Form
key="company"
defaultValues={fields}
resolver={zodResolver(
z.object({
company: z.string().nonempty("Required"),
}),
)}
heading="At what company?"
content={[
{
type: "input",
name: "company",
label: "Company",
placeholder: "Company name",
},
]}
buttons={{
back: "Back",
next: "Next",
}}
onBack={onBack}
onNext={onNext}
/>
),
},
},
],
else: [],
},
},
{
form: {
fields: () => ({
study: ["business", []],
}),
render: ({ fields, onBack, onNext }) => (
<Form
key="study"
defaultValues={fields}
resolver={zodResolver(
z.object({
study: z.string(),
}),
)}
heading="What did you study?"
content={[
{
type: "select",
name: "study",
label: "Study",
placeholder: "Select an option",
options: [
{ value: "business", label: "Business" },
{ value: "health", label: "Health" },
{ value: "technology", label: "Technology" },
{ value: "education", label: "Education" },
],
},
]}
buttons={{
back: "Back",
next: "Submit",
}}
onBack={onBack}
onNext={onNext}
/>
),
},
},
{
return: ({ working, company, study }) => ({
working,
company,
study,
}),
},
];
export default function App() {
const [output, setOutput] = useState<ReturnOutput<Schema> | null>(null);
const onReturn = useCallback<OnReturn<Schema>>((output) => {
setOutput(output);
}, []);
if (output) {
return <Output output={output} onStart={() => setOutput(null)} />;
}
return <Formity<Schema> flow={flow} onReturn={onReturn} />;
}
We need to use the s.Condition type with the corresponding types.
type Schema = {
// ...
struct: [
// ...
s.Condition<{
then: [s.Form<{ company: string }>];
else: [];
}>,
// ...
];
// ...
};
Then, in the flow we need to create an object with the following structure.
const flow: Flow<Schema> = [
// ...
{
condition: {
if: ({ working }) => working === "yes",
then: [
{
form: {
fields: () => ({
company: ["", []],
}),
render: ({ fields, onBack, onNext }) => (
<Form
key="company"
defaultValues={fields}
resolver={zodResolver(
z.object({
company: z.string().nonempty("Required"),
}),
)}
heading="At what company?"
content={[
{
type: "input",
name: "company",
label: "Company",
placeholder: "Company name",
},
]}
buttons={{
back: "Back",
next: "Next",
}}
onBack={onBack}
onNext={onNext}
/>
),
},
},
],
else: [],
},
},
// ...
];
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.