Vuelidate is a fantastic library for form validation in Vue. However, there is one missing link. The workflow to render human-readable validation error messages needs to be implemented by the developer and often results in code duplication, multiple sources of truth, and tightly-coupled components.

The purpose of this story is to share how I’ve solved this problem in my own code through trial and error, resulting in a simple, decoupled, and reusable solution.

The documented way of displaying errors with Vuelidate:

Conditionally show hard-coded errors, checking invalid or dirty status multiple times

Requires knowledge of validations for each input

Brittle — template requires updating if any new validations are added

Not DRY (don’t repeat yourself)

A better way, using a FormGroup component:

There are a few schools of thought here.

Create a component that handles rendering errors, providing a simple but rigid way to display errors. (I provided an example FormGroupWithErrors in the repo) Use a renderless component that passes the data needed via the default scoped-slot, which allows the consumer to decide how and where to show errors.

I prefer the latter. In essence, a component that decorates an input with consistent validation data and messages.

The Form:

Wrap your input in the FormGroup component, which exposes the scoped slot values invalid and errors

component, which exposes the scoped slot values and Full control over how errors are displayed

No knowledge of validation on the input needed

DRY

The Renderless FormGroup Component:

Translates all errors, including interpolation of params, in a single component (I used lodash templating)

Computes a true invalid value based on if the input is dirty and has validation errors

Provides invalid and compiled errors as scoped-slot variables.

In Action:

Code Sandbox:

Vuelidate:

Learn More About Renderless Components:

Code From This Story: