How to handle in forms in Svelte?
Forms! Forms! Forms!
Forms are an integral part of any web application. We can't imagine an application without forms. Generally, the we use forms for
- User registration
- User login
- Subscription
- Contact Form
- Adding/Updating/Removing any kind data to or from the database
In this article, we learn how to create an HTML form. And we also go through how to handle the form validation. This article will not cover the backend APIs required to Post the data into the application. It'll only cover the frontend part.
Lets take a look at this code quickly
<script>
</script>
<main>
<form>
<label for="first_name"> <strong> First Name </strong> </label>
<input id="first_name" name="first_name" type="text" />
<label for="last_name"> <strong> Last Name </strong> </label>
<input id="last_name" name="last_name" type="text" />
<label for="email"> <strong> Email ID </strong> </label>
<input id="email" name="email" type="email" />
<br />
<button type="submit">Save</button>
</form>
</main>
<style>
main {
text-align: center;
padding: 1em;
max-width: 240px;
margin: 0 auto;
}
@media (min-width: 640px) {
main {
max-width: none;
}
}
</style>
Most of the code above is already familiar to anyone familiar with HTML. Currently, our form is doing nothing. In case if we click on the Save
button. It'll merely submit the form without checking or validating any input parameters.
Let's handle the submit event first.
<script>
const submitForm = () => alert('You submit the Form.');
</script>
<form on:submit|preventDefault={submitForm}>
.....
</form>
Take a look at this line,<form on:submit|preventDefault={submitForm}>
. We bind the form with the on:submit
handler.
We bind the form with the on:submit handler.
Now, what happens if we submit the form?
It'll show an alert, You submit the form
Please note, the event modifier |preventDefault
. This is equivalent to adding the Event preventDefault
method in the handler.
Let's add some validation on input parameters.
Validation
We have three fields in our Html form:
- First Name
- Last Name
- Email Id
And here are the following validation rules:
- First name, Last name, and Email cannot be null
- First names and last names can only have alphabets.
We'll start with the null validations, eventually we'll add other validations. Let's add the following under the script
tag.
<script>
function isRequired(value) {
return value != null && value !== ""
}
const submitForm = (event) => {
const formData = new FormData(event.target)
let error = false;
for ( let field of formData ) {
const [key, value] = field;
if( !isRequired(value) ) {
alert('Field ' + key + ' is required')
error = true
}
}
if ( !error ) {
alert('You submit the form.')
}
};
</script>
At present, our application is showing the alerts whenever it caught the exceptions. This is not the correct way of displaying errors. We need to display the errors under the fields.
<script>
let errors = {};
function isRequired(value) {
return value != null && value !== ""
}
const submitForm = (event) => {
const formData = new FormData(event.target)
let error_flag = false;
for ( let field of formData ) {
const [key, value] = field;
if( !isRequired(value) ) {
errors[key] = key + ' is required'
error_flag = true
}
}
if ( !error_flag ) {
alert('You submit the form.')
}
};
</script>
<main>
<form on:submit|preventDefault={submitForm}>
<label for="first_name"> <strong> First Name </strong> </label>
<input id="first_name" name="first_name" type="text" />
{#if errors.first_name}
<p><small style="color: red"> { errors.first_name } </small></p>
{/if}
<label for="last_name"> <strong> Last Name </strong> </label>
<input id="last_name" name="last_name" type="text" />
{#if errors.last_name}
<p><small style="color: red"> { errors.last_name } </small></p>
{/if}
<label for="email"> <strong> Email ID </strong> </label>
<input id="email" name="email" type="email" />
{#if errors.email}
<p><small style="color: red"> { errors.email } </small></p>
{/if}
<br />
<button type="submit">Save</button>
</form>
</main>
<style>
main {
text-align: center;
padding: 1em;
max-width: 240px;
margin: 0 auto;
}
@media (min-width: 640px) {
main {
max-width: none;
}
}
</style>
So far so good. Let's add the validation for valid first_name, last_name and email. We need to create two functions isNameValid()
and isEmailValid()
.
Add the following functions under the script
.
function isNameValid( value ) {
return /^[a-zA-Z]$/.test( value )
}
function isEmailValid( value ) {
return /^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$/.test( value )
}
And also
const submitForm = (event) => {
const formData = new FormData(event.target)
let error_flag = false;
for ( let field of formData ) {
...
...
// Validate First name and Last_name
if ( key === 'first_name' || key === 'last_name' ) {
if ( !isNameValid( value ) ) {
errors[key] = key + ' can only have alphabets'
error_flag = true
}
}
// Valid Email
if ( key === 'email' ) {
if ( !isEmailValid( value ) ) {
errors[key] = 'Invalid Email Id'
error_flag = true
}
}
}
...
...
}
If we notice carefully, then we found the regex we put can handle the null fields. So it is safe to remove the the isRequired()
function. Let's refactor the code.
<script>
let errors = {};
function isNameValid( value ) {
return /^[a-zA-Z]$/.test( value )
}
function isEmailValid( value ) {
return /^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$/.test( value )
}
const submitForm = (event) => {
errors = {}
const formData = new FormData(event.target)
let error_flag = false;
for ( let field of formData ) {
const [key, value] = field;
// Validate First name and Last_name
if ( key === 'first_name' || key === 'last_name' ) {
if ( !isNameValid( value ) ) {
errors[key] = key + ' can only have alphabets'
error_flag = true
}
}
// Valid Email
if ( key === 'email' ) {
if ( !isEmailValid( value ) ) {
errors[key] = 'Invalid Email Id'
error_flag = true
}
}
}
if ( !error_flag ) {
alert('You submit the form.')
}
};
</script>
<main>
<form on:submit|preventDefault={submitForm}>
<label for="first_name"> <strong> First Name </strong> </label>
<input id="first_name" name="first_name" type="text" />
{#if errors.first_name}
<p><small style="color: red"> { errors.first_name } </small></p>
{/if}
<label for="last_name"> <strong> Last Name </strong> </label>
<input id="last_name" name="last_name" type="text" />
{#if errors.last_name}
<p><small style="color: red"> { errors.last_name } </small></p>
{/if}
<label for="email"> <strong> Email ID </strong> </label>
<input id="email" name="email" type="email" />
{#if errors.email}
<p><small style="color: red"> { errors.email } </small></p>
{/if}
<br />
<button type="submit">Save</button>
</form>
</main>
<style>
main {
text-align: center;
padding: 1em;
max-width: 240px;
margin: 0 auto;
}
@media (min-width: 640px) {
main {
max-width: none;
}
}
</style>
Now, if you try to submit the form with all valid parameters, then you'll get an alert alert('You submit the form.')
on your screen.
Thats all for this post. In our next post, we'll discuss other ways of handling forms in Svelte.