Skip to content

useFormState

A lightweight composable for form dirty and touched state without validation. Use with plain ref form data or alongside useZodForm when you need state tracking without Zod.

Basic Usage

vue
<script setup lang="ts">
import { useFormState } from "@baklavue/composables";
import { ref } from "vue";

const form = ref({ email: "", name: "" });
const { isDirty, dirtyFields, touched, touchedFields, setFieldTouched, setFieldValue, reset } = useFormState(form);

// Check before navigation
const beforeUnload = () => {
  if (isDirty.value) {
    return "You have unsaved changes";
  }
};
</script>

API

Parameters

typescript
useFormState(data, options?)
ParameterTypeDescription
dataRef<T> | Reactive<T> | () => TForm data (ref, reactive, or getter)
optionsUseFormStateOptionsOptional: { initialValues?: Ref | () => T }

Return Value

PropertyTypeDescription
isDirtyRef<boolean>Whether any field has changed from initial values
dirtyFieldsRef<Record<string, boolean>>Per-field dirty state
touchedRef<boolean>Whether any field has been blurred
touchedFieldsRef<Record<string, boolean>>Per-field touched state
setFieldTouched(path: string, value?: boolean) => voidMark a field as touched
setFieldValue(path: string, value: unknown) => voidProgrammatically set a field value
reset(initialValues?: unknown) => voidReset touched state and optionally form data
initialValuesRef<unknown>Snapshot of initial values

Unsaved Changes Warning

typescript
const { isDirty } = useFormState(form);

onBeforeRouteLeave((_to, _from, next) => {
  if (isDirty.value) {
    showConfirmDialog({
      title: "Unsaved changes",
      message: "Leave without saving?",
      onConfirm: () => next(),
      onCancel: () => next(false),
    });
  } else {
    next();
  }
});

With useZodForm

useZodForm already provides isDirty, dirtyFields, touched, and touchedFields. Use useFormState when you have a form without Zod validation but still need dirty/touched tracking.