Dirty, Touched, Submitting — Keep Track
Form State Management
Real forms need more than values — they need submitting, dirty, and touched flags so the UI can react sensibly.
What you'll learn
- Track submitting during async submit
- Track dirty (changed from initial)
- Track touched (blurred at least once)
Form value is only part of the story. To build a polished UX you also want to know whether the form is submitting, whether the user has changed anything, and which fields they have actually interacted with.
Submitting
Wrap your submit handler in a flag so you can disable the button and prevent double-submits.
<script setup lang="ts">
import { ref } from 'vue'
const submitting = ref(false)
const error = ref<string | null>(null)
async function submit() {
submitting.value = true
error.value = null
try {
await api.save()
} catch (e) {
error.value = (e as Error).message
} finally {
submitting.value = false
}
}
</script>
<template>
<button :disabled="submitting" @click="submit">
{{ submitting ? 'Saving…' : 'Save' }}
</button>
<p v-if="error">{{ error }}</p>
</template> Dirty Tracking
A form is dirty when its current values differ from the initial snapshot. Compare against the original state.
import { ref, computed } from 'vue'
const initial = { name: 'Ada', email: 'ada@example.com' }
const form = ref({ ...initial })
const isDirty = computed(() =>
JSON.stringify(form.value) !== JSON.stringify(initial)
) Use isDirty to enable a Save button, or warn before navigating away with the beforeunload event.
Touched Tracking
A field is touched after it has been blurred at least once. Hide errors until that happens to avoid yelling at users before they have typed.
import { reactive } from 'vue'
const touched = reactive<Record<string, boolean>>({})
function touch(field: string) {
touched[field] = true
} <input v-model="form.email" @blur="touch('email')" />
<p v-if="touched.email && errors.email">{{ errors.email }}</p> VeeValidate’s useForm bundles all of these (isSubmitting, meta.dirty, meta.touched) for free, which is why it pays off as forms grow.
Submitting & Error Handling →