Skip to content

Vanilla-IceCream/vue-formor

Repository files navigation

vue-formor

Form validation for Vue in composition functions with Valibot.

The main branch refers to the vue-formor v5 release. Check out the v4.x branch for v4.

If you need to use valibot v0.30 or lower, please install vue-formor v4.x instead.

Installation

Install vue-formor with your favorite package manager:

$ npm i vue-formor
# or
$ yarn add vue-formor
# or
$ pnpm i vue-formor
# or
$ bun add vue-formor

Note

Don't forget to install valibot.

Usage

<script lang="ts" setup>
import { reactive, toRef } from 'vue';
import { useSchema } from 'vue-formor';
import * as v from 'valibot';

interface BasicForms {
  email?: string;
  password?: string;
}

const state = reactive({
  loginForm: {} as BasicForms,
  loginValdn: {} as Record<keyof BasicForms, string>,
});

const msgs = {
  required: `This is a required field`,
  email: `This must be a valid email`,
  min: `This must be at least 8 characters`,
};

const schema = useSchema(
  v.object({
    email: v.nullish(v.pipe(v.string(), v.minLength(1, msgs.required), v.email(msgs.email)), ''),
    password: v.nullish(
      v.pipe(v.string(), v.minLength(1, msgs.required), v.minLength(8, msgs.min)),
      '',
    ),
  }),
  toRef(state, 'loginForm'),
  toRef(state, 'loginValdn'),
);

const signIn = () => {
  if (schema.validate()) {
    console.log('validated data =', state.loginForm);
  }
};
</script>

<template>
  <fieldset>
    <legend>Basic Forms</legend>

    <form>
      <div class="flex gap-2">
        <label>Email:</label>
        <input v-model="state.loginForm.email" type="email" />
        <div class="text-red-500">{{ state.loginValdn.email }}</div>
      </div>

      <div class="flex gap-2">
        <label>Password:</label>
        <input v-model="state.loginForm.password" type="password" />
        <div class="text-red-500">{{ state.loginValdn.password }}</div>
      </div>

      <button type="button" @click="signIn">Sign in</button>
    </form>

    <pre>{{ state.loginForm }}</pre>

    <pre>{{ state.loginValdn }}</pre>
  </fieldset>
</template>

<style scoped>
.flex {
  display: flex;
}

.gap-2 {
  gap: 0.5rem;
}

.text-red-500 {
  --un-text-opacity: 1;
  color: rgba(239, 68, 68, var(--un-text-opacity));
}
</style>

Documentation

To learn more about vue-formor, check its documentation.

Examples

See ./examples.

Playground