There is more infrastructure and technology to an inputfield than you might expect at first glance.

In your application, admins shouldn't be able to create a user that has the same username or email of another user. You want to avoid duplicated entries. But when is the right time to display that your input was meaningless? You should get that information ahead of time. Way before you hit the big submit button, just to find out that the user already exists and you have to go search for them. The time you needed to tediously fill in all the fields for that user? Wasted!

Today we are going to build one ot these inputs, to ease filling in those forms.

What are we building?

  • An inputfield to do realtime checking if a user already exists in the system
  • Finding out what data is required for this input field
  • Combining HTTP, Form, Ajax and Validation to get feedback before submission
  • Below, you can find a little example of how this could work in action.

Fill in the input now and get feedback right away.

What looks like no big deal, requires a lot of prep work. Open your devtools and inspect the network tab. Here you can click XHR to only listen to AJAX calls. When typing another username, you will see the results.

The devtools are your tool, to make sure that the requested data correctly gets to the front-end as expected. To see what that data looks like, click on Preview. I prepared a little REST API with fake data, so you can test for usernames and e-mail addresses. You can open that URL to test how the API works. Click the button below to see all users that start with "jo".

The REST API is made to deliver pure data. No HTML, no extra load. This makes loading additional data on the fly easier and also fast. In our case, we get a bunch of JSON data.

Becoming aware of your information architecture

Note

Before you start designing and developing that fancy input, you should be aware of the information architecture at your disposal.

This step is absolutely crucial!

Are you responsible for both front, and back-end but have little understanding of the underlying system? This sucks!

Do you have a back-end developer in your project you can turn to? Get in touch with them! Let them know, you want to asynchronously fetch data for a more interactive user interface. Let them know that you need a way to find out if that user already exists using a REST API. Most full-stack solutions come with their own way of setting this up. Confluence for instance, has a well documented API. Even Wordpress offers a REST API to retrieve a list of users. All those APIs have in common, that they deliver JSON data.

Do you have trouble finding a way? get in touch with me.

If you have the freedom to create your own API, which is very rarely the case, I recommend to get started with ProcessWire for PHP (The test API is based on it!) or express for NodeJS servers.

If for the sake of the guide, you are out of luck and there is no API at your hands, make sure to follow through, using the testing API I created for you.

Building the asynchronous input validation mechanism

To start, we need a simple form with an input. No magic here. Right now, you do not have to care about what the action of the form is, since we just have to take care about the input. However, it is always recommended to use a form to group together any inputs used on your website.

<form method="POST" name="createuser">
	<label for="username">Username</label>
	<input required type="text" name="username">
	<input type="submit">
</form>

Let's evaluate our options for validating the input. We could use the input attribute pattern and create a regex list of all users that are not allowed to pick. However, this would require to place your entire userbase into one input field.

The performance-wise better option you have here, is to perform an AJAX call to the REST API, whenever a username is entered. Optionally, you can debounce the input to avoid flooding the server.

You can do that easily with an async function and fetch.

async function getSimilarUser(username) {
	let response = await fetch(`https://happy-css.com/api/users?limit=1&name=${username}`)
	return response.json()
}

When the input matches a name in the database, we set a pattern attribute Validation is then controlled via the constraint validation API.

The only two methods you need for input validation

There are two functions that make custom validation and real-time checking possible:

element.setCustomValidity('User already exists')

This will let you set custom error messages for inputfields. Setting this to an empty string, makes the input valid. But only if no other constraints, like the required attribute, mark the input as invalid. By the way, you can style invalid inputs with the :invalid pseudo selector.

async function isUserValid(target) {
	let username = target.value
	let users = await getSimilarUser(username)
	if (users.length) {
		let existingUsername = users[0].name
		if (existingUsername == username) {
			target.setCustomValidity(`The user "${username}" already exists`)
			return false
		}
	}
	target.setCustomValidity('')
	return true
}

element.reportValidity()

A form reports any errors on submission. If we want to, you can manually report if any fields are invalid. This way, you know that the user is not allowed before you fill in any other inputfields.

usernameInput.addEventListener('input', async (e)=>{
	let isValid = await isUserValid(e.target)
	// optionally, we can re-use the return value if we need to.
	e.target.reportValidity()
})

That's it! You can combine your REST API with your forms. You can use your favorite HTTP client like axios, jquery or similar. However, by using the elegant async/await syntax together with fetch, you will only require just a few lines of code and use browser native code. Development comfort is important!

How do you charter unknown server territory?

Don't get stuck connecting forms and servers.
Get free on-spot advice delivered to your inbox.

Join the list