Appearance
Vue ValidationErrors Component
Displays form validation errors in a styled error box with an icon, a summary message, and a bulleted list of individual error messages. Renders only when errors are present.
When to use
Use this component anywhere you need to display one or more validation errors in a styled error box. It pairs naturally with useForm to show form.errors after submission or during live validation.
The pattern
Accept an errors array and a summaryMessage string. Use a computed to gate rendering — show the block only when errors exist and the show prop is true.
With useForm
Wire the component to a form composable by binding :errors and gating display on form.touched so errors appear only after the first submission attempt.
vue
<script setup>
import { useForm } from "./use-form.js";
import ValidationErrors from "./ValidationErrors.vue";
const form = useForm({
data() {
return { name: "" };
},
validate(input) {
const errors = [];
if (!input.name) {
errors.push({ message: "Name is required" });
}
return errors;
},
async submit(input) {
await save(input);
},
});
</script>
<template>
<form @submit.prevent="form.submit()">
<ValidationErrors
:errors="form.errors"
:show="form.touched"
/>
<input v-model="form.data.name" />
<button type="submit">Save</button>
</form>
</template>Custom summary message
Override the default summary text for more specific copy.
vue
<ValidationErrors
:errors="form.errors"
summaryMessage="Please correct the following:"
/>Implementing the ValidationErrors component
The component uses v-if on a computed that combines the show prop and the errors array length. Each error object needs a message property, matching the output of schema validation libraries.
vue
<script setup>
import { computed } from "vue";
const props = defineProps({
summaryMessage: {
type: String,
default: "Fix these problems and try again:",
},
show: {
type: Boolean,
default: true,
},
errors: {
type: Array,
default: null,
},
});
const showErrors = computed(() => {
return props.show && props.errors?.length > 0;
});
</script>
<template>
<div v-if="showErrors" class="ValidationError">
<span class="Icon" role="presentation">⚠</span>
<div>
<p>{{ summaryMessage }}</p>
<ul>
<li v-for="error in errors">
{{ error.message }}
</li>
</ul>
</div>
</div>
</template>Conditional rendering with v-if
The v-if="showErrors" directive hides the entire block when there are no errors, avoiding empty containers in the DOM.
The show prop
The show prop lets the parent control visibility independently of whether errors exist. This is useful for hiding errors until the user has interacted with the form by checking form.touched.
Icon as presentation
The error icon is decorative (role="presentation"). The text content carries the meaning, so screen readers skip the icon.
Trade-offs
- Flat error list — Errors render as a flat bulleted list. There is no built-in way to associate errors with specific fields. For field-level inline errors, a separate per-field error component is needed.
- Fixed layout — The icon + text grid layout is baked into the component. Different visual treatments (toast, banner, inline) would need separate components or significant prop-driven variants.
- No transitions — The block appears and disappears instantly. Adding
<Transition>around thev-ifblock would smooth the show/hide experience.