Mantine Form

mantinedev/skills/skills/mantine-form

作者 mantinedev607846dbc328無授權條款63 個星標收錄於 2026年10月8日更新於 2026年10月8日儲存庫4 天前更新

Build forms using @mantine/form. Use this skill when: (1) setting up a form with useForm, (2) adding validation rules, schema validation (zod, valibot, arktype) or async validation, (3) working with nested object or array fields, (4) sharing form state across components with createFormContext, (5) choosing between controlled and uncontrolled mode, (6) reading form values during render with form.useWatchValue, (7) using the standalone useField hook, or (8) any task involving useForm, getInputProps, onSubmit, insertListItem, or form validation.

AI 產生的概覽

指導在 Mantine 9.x 中使用 @mantine/form 建立表單,涵蓋初始化、驗證、模式與欄位綁定。

功能
此技能提供在 Mantine 9.x 中使用 @mantine/form 函式庫建立表單的說明。內容涵蓋以 useForm 初始化表單、透過 getInputProps 與 form.key 綁定輸入、以 onSubmit 處理送出,以及透過規則物件、schema 解析器(zod、valibot、arktype)或函式進行驗證。它也說明非受控與受控模式的差異、重新渲染行為,並指向兩份隨附參考文件以了解進階模式與完整 API。
適用情境
適用於建立或修改 Mantine 表單、加入驗證規則或 schema 驗證、處理巢狀物件或陣列欄位、在元件之間共享表單狀態,或使用 useForm、useField、createFormContext 等 hook 時。
執行需求
專案中需要 @mantine/form 套件(Mantine 9.x)。選用的 schema 驗證需要 zod、valibot 或 arktype 等 Standard Schema 函式庫。僅在取得 Mantine 文件或使用選用的 Mantine MCP 伺服器時涉及網路存取。不含指令碼,只有說明與兩份參考文件。

Mantine Form Skill

Written for Mantine 9.x.

Core Workflow

1. Set up the form

Uncontrolled mode is the recommended mode for all forms. The default is 'controlled', so set it explicitly.

tsx
const form = useForm({  mode: 'uncontrolled',  initialValues: {    email: '',    age: 0,  },  validate: {    email: isEmail('Invalid email'),    age: isInRange({ min: 18 }, 'Must be at least 18'),  },});

2. Wire inputs with getInputProps

In uncontrolled mode every input needs key={form.key('path')}. Without it the input does not update after form.setFieldValue, form.setValues or form.reset.

tsx
<TextInput label="Email" key={form.key('email')} {...form.getInputProps('email')} /><NumberInput label="Age" key={form.key('age')} {...form.getInputProps('age')} />

Checkboxes and switches need { type: 'checkbox' }:

tsx
<Checkbox  label="I agree"  key={form.key('agreed')}  {...form.getInputProps('agreed', { type: 'checkbox' })}/>

Select, NumberInput, Radio.Group, Checkbox.Group and other Mantine inputs with a value / onChange pair work with plain getInputProps and a key:

tsx
<Radio.Group label="Delivery" key={form.key('delivery')} {...form.getInputProps('delivery')}>  <Radio value="standard" label="Standard" />  <Radio value="express" label="Express" /></Radio.Group>

For standalone radios without Radio.Group, use form.getInputProps('color', { type: 'radio', value: 'red' }) and add key={form.key('color')} to each radio.

Components without an error prop (Slider, RangeSlider, Rating, SegmentedControl, Chip.Group) need { withError: false }, and you render the error yourself:

tsx
<Slider key={form.key('stock')} {...form.getInputProps('stock', { withError: false })} />{form.errors.stock && <Text c="red" size="sm">{form.errors.stock}</Text>}

3. Handle submission

tsx
<form onSubmit={form.onSubmit((values) => console.log(values))}>  ...  <Button type="submit">Submit</Button></form>

onSubmit only calls the handler when validation passes. If the handler returns a promise, form.submitting is true until it settles. To handle failures:

tsx
form.onSubmit(  (values, event) => save(values),  (errors, values, event) => console.log('Validation failed', errors) // { 'user.email': 'Invalid email' });

Validation

Rules object (most common)

tsx
validate: {  name: isNotEmpty('Required'),  email: isEmail('Invalid email'),  password: hasLength({ min: 8 }, 'Min 8 chars'),  confirmPassword: matchesField('password', 'Passwords do not match'),}

Schema (zod, valibot, arktype and other Standard Schema libraries)

tsx
import { z } from 'zod/v4';import { schemaResolver, useForm } from '@mantine/form';
const schema = z.object({  email: z.email({ error: 'Invalid email' }),  age: z.number().min(18, { error: 'Must be at least 18' }),});
const form = useForm({  mode: 'uncontrolled',  initialValues: { email: '', age: 0 },  validate: schemaResolver(schema, { sync: true }),});

schemaResolver is built in: no resolver package is needed. Pass { sync: true } for synchronous schemas so that form.validate() returns a plain result instead of a Promise.

Function (for cross-field logic)

tsx
validate: (values) => ({  endDate: values.endDate < values.startDate ? 'End must be after start' : null,});

When to validate

By default fields are validated on submit only.

tsx
validateInputOnChange: true,            // also validate every field when it changesvalidateInputOnChange: ['email'],       // only the listed fieldsvalidateInputOnBlur: ['email'],         // same options, on blurvalidateInputOnBlur: [`members.${FORM_INDEX}.email`], // list items, FORM_INDEX is exported from @mantine/form

With validation on blur, an error that appears when the user presses the submit button shifts the layout, and the click can miss the button. Keep the submit button in a place that does not move when errors appear (for example a footer with fixed position), or validate on change instead.

Modes

'uncontrolled' (recommended)'controlled' (default)
Values storageRefReact state
form.valuesNot updated, use form.getValues()Updated on every change
Re-renders on value changeNoYes
Input propsdefaultValue + onChangevalue + onChange
key={form.key(path)} on inputsRequiredNot needed

What rerenders in uncontrolled mode

  • Typing in an input does not rerender the form.
  • form.getValues() during render is not updated by typing. To show or hide part of the form based on a value, use form.useWatchValue(path). Nested paths work: form.useWatchValue('members.0.role').
  • setFieldValue, setValues, insertListItem, removeListItem, reorderListItem, reset and initialize do rerender, so rendering a list from form.getValues().items.map(...) is correct.
  • form.errors, form.isDirty(), form.isDirty('path'), form.isTouched(), form.submitting and form.validating can be used during render in both modes: the form rerenders when they change.
tsx
const shipsInternationally = form.useWatchValue('shipsInternationally');

References

For anything beyond a basic form, read both references before writing code:

  • references/patterns.md [blocked] — read for: reusing one form for different records (edit dialogs), focusing the first invalid field, more than one submit button, changing a value while the user types, nested objects, array fields, lists inside lists and formRootRule, async validation (rules and async schemas), conditional fields, conditional validation, multi-step forms, loading initial values from a server, saving and setting a new baseline, controlling a form from outside its component, custom inputs, form context across components, transformValues, standalone useField, server errors after submission
  • references/api.md [blocked] — read for everything else. It is the only place that lists every useForm option and return member (watch, onValuesChange, enhanceGetInputProps, resetField, clearFieldError, touchTrigger and others), plus useField, createFormContext, createFormActions, schemaResolver, built-in validators and types

Looking things up

If the references do not cover what you need, do not guess:

  • If the Mantine MCP server (@mantine/mcp-server) is connected, use search_docs and get_item_doc
  • Otherwise fetch https://mantine.dev/llms.txt and open the linked form pages

來源與署名

來源:mantinedev/skills位於skills/mantine-form提交607846d

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架