Server-Side Errors
Handle validation errors returned from an API. Use setError() to display server errors on specific fields, clearErrors() to dismiss them, and getErrors() to read the current error state.
What this example covers:
- Setting server-side errors with
form.setError(field, message) - Clearing errors with
form.clearErrors() - Reading all errors with
form.getErrors() - Showing a loading state with
getFormState().isSubmitting
Live Demo
JavaScript
The handleSubmit callback simulates an API call. If the server returns an error, setError() attaches it to the relevant field. The form's isSubmitting state is managed automatically during async submissions.
js
Alpine.data('serverErrorsForm', () => ({
result: '',
showResult: false,
form: Alpine.Form(
{ email: '', username: '' },
{
config: {
validationMode: 'onTouched',
validations: {
email(value) {
if (!value) return { message: 'Email is required' };
},
username(value) {
if (!value) return { message: 'Username is required' };
},
},
},
},
),
async handleSubmit(data) {
// Simulate a server response with errors
await new Promise((r) => setTimeout(r, 800));
const raw = Alpine.raw(data);
if (raw.email === 'taken@example.com') {
this.form.setError('email', 'This email is already registered');
return;
}
if (raw.username === 'admin') {
this.form.setError('username', 'This username is not available');
return;
}
this.showResult = true;
this.result = 'Registration successful!\n' + JSON.stringify(Alpine.raw(data), null, 2);
},
}));HTML
The submit button is disabled while the form is submitting, and its label changes to show a loading state. The state bar shows live error and submission state.
html
<p style="color: #64748b; font-size: 14px; margin-top: 0">
Try email <code>taken@example.com</code> or username <code>admin</code> to trigger server
errors.
</p>
<div x-data="serverErrorsForm">
<form @submit.prevent="form.submit(handleSubmit)">
<div class="field-group">
<label>Email</label>
<input
x-register:form="form.field('email')"
type="email"
placeholder="Try: taken@example.com"
/>
<span
class="field-error"
x-show="!form.getFieldState('email').isValid"
x-text="form.getFieldState('email').error"
></span>
</div>
<div class="field-group">
<label>Username</label>
<input x-register:form="form.field('username')" type="text" placeholder="Try: admin" />
<span
class="field-error"
x-show="!form.getFieldState('username').isValid"
x-text="form.getFieldState('username').error"
></span>
</div>
<div class="btn-group">
<button type="submit" :disabled="form.getFormState().isSubmitting">
<span
x-text="form.getFormState().isSubmitting ? 'Registering...' : 'Register'"
></span>
</button>
<button type="button" @click="form.clearErrors()">Clear Errors</button>
<button type="button" @click="form.reset()">Reset</button>
</div>
</form>
<pre x-show="showResult" x-text="result"></pre>
<div class="state-bar">
<span>Valid: <strong x-text="form.getFormState().isValid"></strong></span>
<span>Submitting: <strong x-text="form.getFormState().isSubmitting"></strong></span>
<span>Errors: <strong x-text="JSON.stringify(form.getErrors())"></strong></span>
</div>
</div>API Reference
js
form.setError('email', 'Already taken'); // Set error on a field
form.clearErrors('email'); // Clear one field
form.clearErrors(); // Clear all
form.getErrors(); // { email: 'Already taken' }