Editing & drafts
Edit forms differ from create forms: the data already exists, only changes should be sent, and losing edits is painful.
Loading data
Initial values often arrive from the server after the form is created. Pass them to reset — they become the new baseline for dirty and changes:
ts
const form = useForm(UpdateUser, { initial: { name: '', email: '', bio: '' } });
onMounted(async () => {
const user = await api.get(`/users/${id}`);
form.reset({ name: user.name, email: user.email, bio: user.bio ?? '' });
});Only changed fields — PATCH
form.changes contains only what the user changed. Together with a partial schema this is a ready PATCH:
ts
const submit = form.handleSubmit(async () => {
await api.patch(`/users/${id}`, form.changes); // { bio: 'New bio' }
});vue
<button :disabled="!form.dirty || form.submitting">Save</button>
<span v-if="form.isDirty('email')">Email will be changed</span>After a successful submit the current values count as saved: dirty becomes false, changes becomes empty. If the handler calls setErrors (the server rejected the data), the changes stay unsaved.
Draft and leave warning
useDraft saves the input and restores it after a reload; useLeaveGuard warns when a tab with unsaved changes is closed:
ts
const form = useForm(Post, { initial: { title: '', body: '' } });
useDraft(form, `post-${id}`);
useLeaveGuard(form);