npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@apatheticwes/validation

v1.0.3

Published

A lightweight schema-based validation librarie, with a holistic approach to asynchronicity

Downloads

4

Readme

Validation

A schema-driven validation framework for Vue 3, providing reactive, client-side validation.

The Validation composable is a reactive form object. This object is consumed by the page component and used in its template, where it will automatically validate any user-entered data.

It requires a set of values (ie. component data) and rules to validate the them. The rules are a JSON-schema that define which inputs on a page need validation, and how.

At a Glance

  • Schema-based. Validation rules and structure may be imported, keeping the component lean
  • Flexible. Simply provide the validation with rules + values
    • use the component's data as values, and provide rules elsewhere (no "black box" set up)
    • optionally, sweep away both rules and values into a schema config (for a very lean component)
  • Reactive. Validation reacts to user input
  • Extensible. Easy to override and add new rules
  • Utilizes prior art. Validators from Vuelidate are leveraged; no need to reinvent the wheel
  • De-coupled. The reactive form-object can be injected directly into the middleware
    • In the middleware a server-generated error (in the JSON error format) may be used to hydrate the validation object
  • Optionated. May be tightly integrated with the ZigZag UI. For example:
    • Dedicated wrappers (or "validation providers") such as z-field.
  • Front-end / back-end "agnostic". The form-object can consume validation errors generated on either client or server
  • Future-looking. Leverages Vue 3 composition API

Getting Started

Setting up a validation schema is easy and flexible enough to handle a variety of use-cases.

Option 1

  • set up the values and their validation rules in an external schema, and import it.
// schemas/validation.js
const coolSchema = { ... };
const coolValues = { ... };

export function useCoolFormValidation() {
  return useValidation(coolSchema, coolValues);
}
// coolComponent.vue
import { useCoolFormValidation } from '@/schemas';

const { form } = useCoolFormValidation();

...
computed() {
  form: () => form
}

The advantage in this set-up is simplicity; the disadvantage is that the component's values are not readily visible to the developer, which may be opaque in the template.

Option 2

  • use your page component's data as values.
  • define the validation schema externally and "curry" them into the useValidation composable
  • use the setValues helper from the composable to asynchronously add values when they're available
// schemas/index.js
const coolSchema = { ... };
export function useCoolFormValidationNoValues() {
  return useValidation(coolSchema);
}
// coolComponent.vue
import { useCoolFormValidationNoValues } from '@/schemas';
const { form, setValues } = useCoolFormValidationNoValues();

...
data() ({
  values: {
    name: '',
    email: '',
  }
}),

beforeCreate() {
  // minor shortcut:
  // after `setValues`, we make `form` a computed prop in the template while we're at it
  this.$options.computed.form = setValues(this.values);
}

Validation object

useValidation creates a reactive form validation object. The returned object matches the same shape as the validation schema, except each field will be decorated/returned as follows:

  • There are be five (5) core properties: $model, $error, $dirty, $invalid and $errors.
  "$model": "horace",
  "$error": false, // helper for: $invalid && $dirty
  "$dirty": false,
  "$invalid": false,
  "$errors": [ ... ]
  • There are be dynamic properties for each specific validation rule added (i.e. required, email, etc)
  // validation props. These are dynamic:
  "required": true,   // passes required check
  "minLength": false, // does not meet minLength criteria
  "email": true,      // passes email validation
  ...

Note the similarities with vuelidate, from which this structure was borrowed.

Portability

Once created, the composable creates a reactive object representating a component's data. Reactive validation bindings will automically update if any data field is updated, and can be surfaced in the template.

Note though, that it is equally possible to export the composable to the middleware where it may be used to hydrate server-side errors; any field or validation that is then updated here will automatically be surfaced in the template where it is used.

First, we create the validation object:

// schemas/index
const schema = { ... };
const values = { ... };
const exampleForm = useValidation(schema, values);

export { exampleForm };

We'd use the exampleForm in a page component as normal, but also, in an action:

export const exampleAction = async ({ commit }) => {
  try {
    const exampleData = await api.settings.getExampleData();
    ...
  } catch (error) {
    import('@/schemas/exampleForm') // WEBPACK conditional import.
      .then((exampleForm) => {
        exampleForm.setErrors(error);
      });
  }
};

Here, we conditionally load the module and hydrate it upon any error(s) originating from the server. That's it! We can now surface server errors anywhere in the page, without needed any conditional logic in the page or elsewhere. If the server response is in the JSON-error format, the framework will unwrap it and even apply it to the corresponding field in the template automatically.

z-field

The z-field component may be used as a field wrapper. It accepts errors array from validation rules, or even a single errors[0].$message if desired. z-field can wrap any other UI components, and act as a decorator for error feedback.

  <z-field
    v-for="(field, key, index) in form"
    :key="'field-' + key"
    :label="key"
    :errors="field.$errors"
    :hint="'Type in something for ' + key"
  >
    <input v-model="field.$model" />
  </z-field>

Notes

When npm i, you'll need to use the --force option, as a peer dependency in vuelidate/validators does not correctly resolve.

References:

Validatable draws inspiration from multiple sources.

Vue Composable: Vue 3 composition API approach to Vee Validate: Vue 3 composition API + "validation provider" component Vuelidate for model based validation Vuetify: Array validation approach