Skip to content

Instantly share code, notes, and snippets.

@HappyTiptoe
Last active October 19, 2023 07:53
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HappyTiptoe/b798357efc7c6bec59af01a5fa252f99 to your computer and use it in GitHub Desktop.
Save HappyTiptoe/b798357efc7c6bec59af01a5fa252f99 to your computer and use it in GitHub Desktop.
Vue.js composable for consuming Vest suites and receiving reactive references to the result and classes. Written in TypeScript and JavaScript.
<!-- Form.vue -->
<script setup lang="ts">
import { reactive } from 'vue'
import { useSuite } from '~/composables/useSuite'
import { suite } from '~/suites/example'
const { res, classes, validate, reset } = useSuite(suite)
const formData = reactive({
email: '',
password: ''
})
function validateField(field: string) {
validate(formData, field)
}
function resetForm() {
formData.email = ''
formData.password = ''
reset()
}
/* - - - */
function handleSubmit() {
// check if form is invalid before submitting
if (!res.value.isValid()) {
return
}
/* ... */
}
</script>
<template>
<form @submit.prevent="handleSubmit">
<label>
Email:
<input
v-model="formData.email"
type="text"
:class="classes('email')"
@input="validateField('email')"
/>
</label>
<label>
Password:
<input
v-model="formData.password"
type="password"
:class="classes('password')"
@input="validateField('password')"
/>
</label>
<button type="submit" :disabled="!res.isValid()">Submit Form</button>
<button type="button" @click="resetForm">Clear Form</button>
</form>
</template>
/* useSuite.ts */
import type { Suite } from 'vest'
import type { CB } from 'vest-utils'
import { computed, ref } from 'vue'
import classnames from 'vest/classnames'
// Duplicate of unexported `SupportedClasses` interface
interface Classes {
valid?: string
tested?: string
invalid?: string
warning?: string
untested?: string
}
// Replace `undefined` with your class names of choice!
const DEFAULT_CLASSES: Classes = {
valid: undefined,
tested: undefined,
invalid: undefined,
warning: undefined,
untested: undefined
}
/**
* Vue composable for interacting with [Vest](https://vestjs.dev) validation suites.
*
* @param {Suite} suite - The Vest validation suite
* @param {Classes} [_classes] - The user-defined state-validity class names
*/
export function useSuite<T extends CB>(suite: Suite<T>, _classes?: Classes) {
// reactive reference to the suite result
const res = ref(suite.get())
// method which returns respective classes depending on field's validity status;
// here, we merge the user's input class names with the default class names
// defined above
const classes = computed(() => {
return classnames(res.value, { ...DEFAULT_CLASSES, ..._classes })
})
// the suite validation method
function validate(...args: Parameters<T>) {
res.value = suite(...args)
}
// the suite reset method
function reset() {
suite.reset()
res.value = suite.get()
}
// the suite reset method for a single field
function resetField(field: string) {
suite.resetField(field)
res.value = suite.get()
}
return { res, classes, validate, reset, resetField }
}
/* useSuite.js */
// Replace `undefined` with your class names of choice!
const DEFAULT_CLASSES = {
valid: undefined,
tested: undefined,
invalid: undefined,
warning: undefined,
untested: undefined
}
/**
* Vue composable for interacting with [Vest](https://vestjs.dev) validation suites.
*
* @param suite - The Vest validation suite
* @param [_classes] - The user-defined state-validity class names
*/
export function useSuite(suite, _classes) {
// reactive reference to the suite result
const res = ref(suite.get())
// method which returns respective classes depending on field's validity status;
// here, we merge the user's input class names with the default class names
// defined above
const classes = computed(() => {
return classnames(res.value, { ...DEFAULT_CLASSES, ..._classes })
})
// the suite validation method
function validate(...args) {
res.value = suite(...args)
}
// the suite reset method
function reset() {
suite.reset()
res.value = suite.get()
}
// the suite reset method for a single field
function resetField(field) {
suite.resetField(field)
res.value = suite.get()
}
return { res, classes, validate, reset, resetField }
}
@ealush
Copy link

ealush commented Mar 9, 2023

@HappyTiptoe
Copy link
Author

Thanks so much for featuring it @ealush!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment