wcz-layout
Version:
83 lines (70 loc) • 2.41 kB
Markdown
---
name: forms
description: "Use when: creating or modifying TanStack Form components, field layouts, validation schemas, submit handling, or custom form controls."
---
# Form Patterns
## Rules
- Always use `useLayoutForm` with pre-defined components.
- Define `width` for all form fields based on the expected content length.
- Reuse Zod schemas from `src/lib/schemas/` which are derived from Drizzle schemas with `createSelectSchema` from table schemas.
- Use translation for labels, helper text, validation messages and submit.
- Reset the form after successful create.
- Use one of the following field based on the use case: `Autocomplete`, `Checkbox`, `DatePicker`, `DateRangePicker`, `DateTimePicker`, `DateTimeRangePicker`, `NumberField`, `RadioGroup`, `Slider`, `SubmitButton`, `Switch`, `TextField`, `TimePicker`, or `TimeRangePicker`.
## File Placement
```
src/routes/<feature>s/-components/ - route-scoped forms
src/lib/schemas/ — Zod schemas (shared between client and server)
wcz-layout/hooks - useLayoutForm hook, useTranslation
```
## Examples
```ts
// Form Component
interface FormProps {
defaultValues: Feature;
onSubmit: (value: Feature) => Promise<void>;
}
export const Form: FC<FormProps> = ({ defaultValues, onSubmit }) => {
const { t } = useTranslation();
const form = useLayoutForm({
defaultValues,
validators: { onChange: FeatureSchema },
onSubmit: async ({ value, formApi }) => {
await onSubmit(value);
formApi.reset();
},
});
return (
<form
onSubmit={(event) => {
event.preventDefault();
event.stopPropagation();
form.handleSubmit();
}}
>
{/* some styling */}
<form.AppField name="name">
{(field) => <field.TextField label={t("Feature.Name")} required sx={{ width: 420 }} />}
</form.AppField>
{/* some styling */}
<form.AppForm>
<form.SubmitButton variant="contained">{t("Submit")}</form.SubmitButton>
</form.AppForm>
</form>
);
};
// Autocomplete
<field.Autocomplete
options={options}
sx={{ width: 250 }}
autoHighlight
autoSelect
autoComplete
loading={isLoading}
textFieldProps={{
label: t("Customer"),
required: true,
}}
/>
// Checkbox
<field.Checkbox label={t("IsThisTrue")} />
```