svelte-forms-lib
svelte-forms-lib copied to clipboard
Support to set field/s error/s imperatively (`setFieldError`/`setErrors`)
Set errors imperatively on certain field/s, while validating (inside the callback provided to onSubmit
) a form or after creating a form.
Problem to solve
As a user I want to be able to call a function which sets an error message on certain field/s.
Intended users
Developer
User experience goal
After creating a form, setting a field's error
const { setFieldError } = createForm({ /* ... */ });
/* Checks if the provided username is available */
async function validateUsernameServerSide(username) {
try {
// -- snip --
} catch (error) {
setFieldError('username', `The username: "${username}" is already taken!`,
}
}
Inside the onSubmit
callback
If you wanted to set a field error message from a server side validation, you
could use helpers from the onSubmit
function which would let you set the
message for a certain field.
const form = createForm({
onSubmit: (values, helpers) => {
try {
// -- snip --
} catch (error) {
helpers.setFieldError('username', `The username: "${username}" is already taken!`,
}
}
});
Proposal
Provide setFieldError
for single fields and setErrors
functions to the API.
-
setFieldError(field: string, message: string)
: Sets the provided message as the error for the field with the name provided onfield
.
Eg:
setFieldError('email', 'The email must belong to the domain "example.com"');
-
setErrors(errors: { [field: string]: string })
: A function that receives an object which holds the field name as thekey
and the error message as thevalue
. Useful to set many error messages at once.
setErrors({
email: 'The email must belong to the domain "example.com"',
password: 'The password is not strong enough',
});
Further details
Setting errors outside of the validation schema when form is validated server-side or by functions that run in parallel and can't be validated by the validation schema.
Documentation
Links / references
- Formik's
setFieldError
: https://formik.org/docs/api/formik#setfielderror-field-string-errormsg-string--void - Formiks's
setErrors
:
This would be great! But today what is the current best approach to handling a server-side rejection like this?
This would be great! But today what is the current best approach to handling a server-side rejection like this?
I ended up writing straight to the error store.
I'm assuming it's something like this:
const { errors } = createForm({
initialValues: {
name: 'test'
},
onSubmit: () => {}
});
errors.set({ name: 'My custom error' });
But I'm using the <Form>
component approach (not createForm
), so seems I don't have access to the error store directly. Any idea on how to get access to that from <Form>
?
I'm assuming it's something like this:
const { errors } = createForm({ initialValues: { name: 'test' }, onSubmit: () => {} }); errors.set({ name: 'My custom error' });
But I'm using the
<Form>
component approach (notcreateForm
), so seems I don't have access to the error store directly. Any idea on how to get access to that from<Form>
?
Oh! Not sure how it would work for the <Form>
component approach TBH.
I can see the <Form>
component exposes the underlying errors
store as prop, by passing it to the <slot />
.
Here is the code: https://github.com/tjinauyeung/svelte-forms-lib/blob/7df1b1df4f02c5ff512e2542c879056ac2d8138d/lib/components/Form.svelte#L51
You should be able to use it like:
<Form let:errors={errors}>
<!-- Do something with the error store here -->
</Form >
Perhaps this way you can write to this?
Thanks for the pointers. But could not get it to work with the errors slot, when trying to call it from the onSubmit()
event of the parent (Function called outside component initialization). But it worked when binding the entire Form and digging out the error store from that, bit hacky, but works.
onSubmit: (values) => {
// Send request and get response
const errors = form.$$.ctx.find((a) => a && a.errors).errors; // Find the error store
errors.set({ name: 'Manual error set' });
}
};
let form;
<Form {...formProps} bind:this={form}>
Thanks @ecker00!