Skip to content

useField

Reactive field state with validation, designed for use with GTInput.

Usage

vue
<script setup>
import { useField } from '@grundtone/vue';
import { required, email } from '@grundtone/vue';

const field = useField({
  validators: [required(), email()],
  validateOn: 'blur',
});
</script>

<template>
  <GTInput
    v-model="field.value.value"
    :error-text="field.errorText.value"
    v-on="field.handlers"
    label="Email"
    type="email"
  />
</template>

In Nuxt, useField is auto-imported.

Options

OptionTypeDefaultDescription
validatorsValidator[][]Array of validator functions from @grundtone/utils
validateOn'input' | 'blur' | 'submit''blur'When to run validation
initialValuestring''Starting value

Return value

PropertyTypeDescription
valueRef<string>The field value
errorTextComputedRef<string | undefined>Error message (shown only after touched)
touchedRef<boolean>Whether the field has been interacted with
isValidComputedRef<boolean>Whether the current value passes all validators
validate()() => ValidationResultManually trigger validation
reset()() => voidReset to initial state
handlersobjectEvent handlers to bind to GTInput via v-on

Validation modes

  • blur (default) — Validates when the field loses focus. Best for most forms.
  • input — Validates on every keystroke. Use for real-time feedback.
  • submit — Only validates when validate() is called manually. Use with useFormValidation.

Available validators

Import from @grundtone/vue (or @grundtone/utils):

FactoryDescription
required(msg?)Non-empty after trim
email(msg?)Valid email format
phone(msg?)Danish phone number (8 digits)
cpr(msg?)Danish CPR number
cvr(msg?)Danish CVR number (modulus 11)
minLength(n, msg?)Minimum character length
maxLength(n, msg?)Maximum character length
pattern(regex, msg?)Custom regex match
url(msg?)Valid HTTP(S) URL
date(msg?)Valid date (day/month/year exist)
datePast(msg?)Date must be in the past
dateFuture(msg?)Date must be in the future
composeValidators(...v)Compose multiple validators into one

All validators (except required) pass on empty strings, so they're optional by default. Combine with required() to make a field mandatory.

The date, datePast, and dateFuture validators expect a "DD-MM-YYYY" format string. For use with GTDateInput, use useDateField which handles the conversion automatically.

Custom validators

A validator is just a function (value: string) => ValidationResult:

ts
import type { Validator } from '@grundtone/vue';

const noSpaces: Validator = (value) =>
  value.includes(' ')
    ? { isValid: false, message: 'No spaces allowed' }
    : { isValid: true };

const field = useField({ validators: [required(), noSpaces] });