CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vee-validate

Painless forms for Vue.js with comprehensive validation, composition API, and component-based approaches.

Pending
Overview
Eval results
Files

state-access.mddocs/

State Access

Composables for accessing reactive form and field state information. These composables provide read-only access to various aspects of form and field state for reactive UI updates and conditional logic.

Capabilities

Field State Access

useFieldValue Composable

Gets reactive access to a field's current value.

/**
 * Gets reactive access to a field's current value
 * @param path - Field path (uses injected field context if omitted)
 * @returns Computed ref to field value
 */
function useFieldValue<TValue = unknown>(path?: MaybeRefOrGetter<string>): ComputedRef<TValue | undefined>;

useFieldError Composable

Gets reactive access to a field's error message.

/**
 * Gets reactive access to a field's error message
 * @param path - Field path (uses injected field context if omitted)
 * @returns Computed ref to field error message
 */
function useFieldError(path?: MaybeRefOrGetter<string>): ComputedRef<string | undefined>;

Field State Examples:

import { useFieldValue, useFieldError, useField } from "vee-validate";

// Using with explicit path
const email = useFieldValue('email');
const emailError = useFieldError('email');

// Using within field context (path omitted)
const EmailField = {
  setup() {
    const field = useField('email', 'required|email');
    
    // These will automatically use the 'email' field context
    const value = useFieldValue(); // Same as field.value
    const error = useFieldError();  // Same as field.errorMessage
    
    return { value, error };
  }
};

// Reactive field path
const currentField = ref('username');
const fieldValue = useFieldValue(currentField);
const fieldError = useFieldError(currentField);

// Watch field changes
watchEffect(() => {
  console.log(`${currentField.value} value:`, fieldValue.value);
  if (fieldError.value) {
    console.log(`${currentField.value} error:`, fieldError.value);
  }
});

// Computed properties based on field state
const isEmailValid = computed(() => {
  const emailVal = useFieldValue('email');
  const emailErr = useFieldError('email');
  return emailVal.value && !emailErr.value;
});

Form State Access

useFormValues Composable

Gets reactive access to all form values.

/**
 * Gets reactive access to all form values
 * @returns Computed ref to form values object
 */
function useFormValues<TValues extends GenericObject = GenericObject>(): ComputedRef<Partial<TValues>>;

useFormErrors Composable

Gets reactive access to all form errors.

/**
 * Gets reactive access to all form errors
 * @returns Computed ref to form errors object
 */
function useFormErrors<TValues extends GenericObject = GenericObject>(): ComputedRef<FormErrors<TValues>>;

type FormErrors<TValues extends GenericObject> = Partial<Record<Path<TValues> | '', string | undefined>>;

Form State Examples:

import { useFormValues, useFormErrors, useForm } from "vee-validate";

// Setup form context
const { handleSubmit } = useForm();

// Access form state
const formValues = useFormValues();
const formErrors = useFormErrors();

// Watch form changes
watchEffect(() => {
  console.log('Current form values:', formValues.value);
  console.log('Current form errors:', formErrors.value);
});

// Computed properties based on form state
const hasErrors = computed(() => {
  return Object.keys(formErrors.value).length > 0;
});

const formDataSummary = computed(() => {
  const values = formValues.value;
  return {
    fieldCount: Object.keys(values).length,
    filledFields: Object.values(values).filter(v => v !== '' && v != null).length,
    hasData: Object.values(values).some(v => v !== '' && v != null)
  };
});

// Form validation summary
const validationSummary = computed(() => {
  const errors = formErrors.value;
  const errorFields = Object.keys(errors).filter(key => errors[key]);
  
  return {
    isValid: errorFields.length === 0,
    errorCount: errorFields.length,
    errorFields,
    firstError: errorFields.length > 0 ? errors[errorFields[0]] : null
  };
});

Validation State Access

useIsFieldDirty Composable

Checks if field value differs from initial value.

/**
 * Checks if field value differs from initial value
 * @param path - Field path (uses injected field context if omitted)
 * @returns Computed ref to field dirty state
 */
function useIsFieldDirty(path?: MaybeRefOrGetter<string>): ComputedRef<boolean>;

useIsFieldTouched Composable

Checks if field has been interacted with.

/**
 * Checks if field has been interacted with
 * @param path - Field path (uses injected field context if omitted)
 * @returns Computed ref to field touched state
 */
function useIsFieldTouched(path?: MaybeRefOrGetter<string>): ComputedRef<boolean>;

useIsFieldValid Composable

Checks if field passes validation.

/**
 * Checks if field passes validation
 * @param path - Field path (uses injected field context if omitted)
 * @returns Computed ref to field valid state
 */
function useIsFieldValid(path?: MaybeRefOrGetter<string>): ComputedRef<boolean>;

Field Validation State Examples:

import { 
  useIsFieldDirty, 
  useIsFieldTouched, 
  useIsFieldValid,
  useField 
} from "vee-validate";

// Field state composables with explicit paths
const isEmailDirty = useIsFieldDirty('email');
const isEmailTouched = useIsFieldTouched('email');
const isEmailValid = useIsFieldValid('email');

// Combined field state checks
const emailFieldStatus = computed(() => {
  if (!isEmailTouched.value) return 'untouched';
  if (!isEmailValid.value) return 'invalid';
  if (isEmailDirty.value) return 'modified';
  return 'valid';
});

// Using within field context
const EmailField = {
  setup() {
    useField('email', 'required|email');
    
    const isDirty = useIsFieldDirty();
    const isTouched = useIsFieldTouched();
    const isValid = useIsFieldValid();
    
    const showValidationIcon = computed(() => {
      return isTouched.value && (isValid.value || !isValid.value);
    });
    
    const fieldClasses = computed(() => ({
      'field-untouched': !isTouched.value,
      'field-dirty': isDirty.value,
      'field-valid': isTouched.value && isValid.value,
      'field-invalid': isTouched.value && !isValid.value
    }));
    
    return {
      isDirty,
      isTouched,
      isValid,
      showValidationIcon,
      fieldClasses
    };
  }
};

// Reactive field paths
const activeField = ref('username');
const isActiveFieldDirty = useIsFieldDirty(activeField);
const isActiveFieldValid = useIsFieldValid(activeField);

// Watch state changes
watch([isActiveFieldDirty, isActiveFieldValid], ([dirty, valid]) => {
  console.log(`${activeField.value} state:`, { dirty, valid });
});

Form Validation State Access

useIsFormDirty Composable

Checks if any form field is dirty.

/**
 * Checks if any form field is dirty
 * @returns Computed ref to form dirty state
 */
function useIsFormDirty(): ComputedRef<boolean>;

useIsFormTouched Composable

Checks if any form field is touched.

/**
 * Checks if any form field is touched
 * @returns Computed ref to form touched state
 */
function useIsFormTouched(): ComputedRef<boolean>;

useIsFormValid Composable

Checks if entire form is valid.

/**
 * Checks if entire form is valid
 * @returns Computed ref to form valid state
 */
function useIsFormValid(): ComputedRef<boolean>;

useIsSubmitting Composable

Checks if form is currently submitting.

/**
 * Checks if form is currently submitting
 * @returns Computed ref to form submitting state
 */
function useIsSubmitting(): ComputedRef<boolean>;

useIsValidating Composable

Checks if form is currently validating.

/**
 * Checks if form is currently validating
 * @returns Computed ref to form validating state
 */
function useIsValidating(): ComputedRef<boolean>;

Form Validation State Examples:

import { 
  useIsFormDirty,
  useIsFormTouched,
  useIsFormValid,
  useIsSubmitting,
  useIsValidating,
  useForm
} from "vee-validate";

// Setup form
const { handleSubmit } = useForm();

// Form state composables
const isFormDirty = useIsFormDirty();
const isFormTouched = useIsFormTouched();
const isFormValid = useIsFormValid();
const isSubmitting = useIsSubmitting();
const isValidating = useIsValidating();

// Combined form state
const formState = computed(() => ({
  dirty: isFormDirty.value,
  touched: isFormTouched.value,
  valid: isFormValid.value,
  submitting: isSubmitting.value,
  validating: isValidating.value
}));

// Form status computed properties
const canSubmit = computed(() => {
  return isFormValid.value && !isSubmitting.value && !isValidating.value;
});

const showUnsavedWarning = computed(() => {
  return isFormDirty.value && !isSubmitting.value;
});

const formStatus = computed(() => {
  if (isSubmitting.value) return 'submitting';
  if (isValidating.value) return 'validating';
  if (!isFormTouched.value) return 'pristine';
  if (!isFormValid.value) return 'invalid';
  if (isFormDirty.value) return 'modified';
  return 'valid';
});

// Button states based on form state
const submitButtonProps = computed(() => ({
  disabled: !canSubmit.value,
  loading: isSubmitting.value,
  text: isSubmitting.value ? 'Submitting...' : 'Submit'
}));

const resetButtonProps = computed(() => ({
  disabled: !isFormDirty.value || isSubmitting.value,
  visible: isFormDirty.value
}));

// Form progress indicator
const formProgress = computed(() => {
  const touched = isFormTouched.value;
  const valid = isFormValid.value;
  const dirty = isFormDirty.value;
  
  if (!touched) return { step: 0, label: 'Start filling the form' };
  if (!valid) return { step: 1, label: 'Fix validation errors' };
  if (dirty) return { step: 2, label: 'Ready to submit' };
  return { step: 3, label: 'Form completed' };
});

// Watch form state changes
watchEffect(() => {
  if (showUnsavedWarning.value) {
    // Show browser warning about unsaved changes
    window.addEventListener('beforeunload', handleBeforeUnload);
  } else {
    window.removeEventListener('beforeunload', handleBeforeUnload);
  }
});

const handleBeforeUnload = (e: BeforeUnloadEvent) => {
  e.preventDefault();
  e.returnValue = 'You have unsaved changes. Are you sure you want to leave?';
  return e.returnValue;
};

Advanced State Access Patterns

Custom State Selectors

Creating custom computed properties based on multiple state sources.

import { 
  useFormValues, 
  useFormErrors, 
  useIsFormValid,
  useIsFormDirty 
} from "vee-validate";

// Custom selectors
const formValues = useFormValues();
const formErrors = useFormErrors();
const isFormValid = useIsFormValid();
const isFormDirty = useIsFormDirty();

// Complex state selectors
const formCompleteness = computed(() => {
  const values = formValues.value;
  const requiredFields = ['name', 'email', 'phone'];
  const filledRequired = requiredFields.filter(field => values[field]).length;
  
  return {
    percentage: (filledRequired / requiredFields.length) * 100,
    filledFields: filledRequired,
    totalRequired: requiredFields.length,
    isComplete: filledRequired === requiredFields.length
  };
});

const validationSummary = computed(() => {
  const errors = formErrors.value;
  const errorEntries = Object.entries(errors).filter(([_, error]) => error);
  
  return {
    hasErrors: errorEntries.length > 0,
    errorCount: errorEntries.length,
    fields: errorEntries.map(([field, error]) => ({ field, error })),
    severity: errorEntries.length > 3 ? 'high' : errorEntries.length > 0 ? 'medium' : 'none'
  };
});

const formHealthScore = computed(() => {
  const valid = isFormValid.value;
  const dirty = isFormDirty.value;
  const completeness = formCompleteness.value.percentage;
  const errors = validationSummary.value.errorCount;
  
  let score = 0;
  if (valid) score += 40;
  if (completeness > 80) score += 30;
  if (dirty && valid) score += 20;
  if (errors === 0) score += 10;
  
  return {
    score,
    grade: score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 70 ? 'C' : 'D',
    status: score >= 90 ? 'excellent' : score >= 80 ? 'good' : score >= 70 ? 'fair' : 'poor'
  };
});

Install with Tessl CLI

npx tessl i tessl/npm-vee-validate

docs

configuration-rules.md

core-validation.md

field-management.md

form-actions.md

form-management.md

index.md

state-access.md

vue-components.md

tile.json