Dynamic form
In this example, we render a dynamic form with the fields coming from the backend.
type FieldType = 'string' | 'email' | 'int'
type Field = { name: string; type: FieldType }
const getFields = () => {
// This would come from a database
const fields: Field[] = [
{ name: 'firstName', type: 'string' },
{ name: 'email', type: 'email' },
{ name: 'age', type: 'int' },
]
return fields
}
const typeSchemas = {
string: z.string(),
email: z.string().email(),
int: z.number().int(),
}
const fieldSchema = (type: FieldType) => typeSchemas[type]
const fieldsSchema = (fields: Field[]) =>
z.object(
fields.reduce(
(obj, field) => ({ ...obj, [field.name]: fieldSchema(field.type) }),
{},
),
)
const mutation = makeDomainFunction(fieldsSchema(getFields()))(
async (values) => values,
)
export function loader(_args: LoaderArgs) {
return { fields: getFields() }
}
export const action: ActionFunction = async ({ request }) =>
formAction({ request, schema: fieldsSchema(getFields()), mutation })
export default () => {
const { fields } = useLoaderData<typeof loader>()
return <Form schema={fieldsSchema(fields)} />
}
Dynamic form
In this example, we render a dynamic form with the fields coming from the backend.
type FieldType = 'string' | 'email' | 'int'
type Field = { name: string; type: FieldType }
const getFields = () => {
// This would come from a database
const fields: Field[] = [
{ name: 'firstName', type: 'string' },
{ name: 'email', type: 'email' },
{ name: 'age', type: 'int' },
]
return fields
}
const typeSchemas = {
string: z.string(),
email: z.string().email(),
int: z.number().int(),
}
const fieldSchema = (type: FieldType) => typeSchemas[type]
const fieldsSchema = (fields: Field[]) =>
z.object(
fields.reduce(
(obj, field) => ({ ...obj, [field.name]: fieldSchema(field.type) }),
{},
),
)
const mutation = makeDomainFunction(fieldsSchema(getFields()))(
async (values) => values,
)
export function loader(_args: LoaderArgs) {
return { fields: getFields() }
}
export const action: ActionFunction = async ({ request }) =>
formAction({ request, schema: fieldsSchema(getFields()), mutation })
export default () => {
const { fields } = useLoaderData<typeof loader>()
return <Form schema={fieldsSchema(fields)} />
}