4 min read
Now, most people who have built websites have included forms. Regular text elements, number, select (dropdown), checkboxes and radio buttons.
A situation I've often encountered is where we need the user to choose from a very long list of options. The easiest thing to do is to put all the options into a select element. However, this is impractical because...
An auto complete form. We could have a huge list and show only those relevant to the user. We don't need to load all the results into the HTML, we can simply load the ones we need as the user types.
This is the technique used in many websites where there are a lot of options to choose from. e-commerce, marketplaces, classifieds, social media, e.t.c.
It may seem like the implementation is complex, especially with libraries like typeahead.js, however, it is actually rather simple.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>
Demo auto complete
</title>
</head>
<body>
<h2>The form</h2>
<form>
<input type="text" name="name" id="name_input">Name
<br/>
<input type="submit">
</form>
</body>
</html>
To create an autocomplete form, we will use the HTML5 datalist
tag, so we modify it to look like this.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>
Demo auto complete
</title>
</head>
<body>
<h2>The form</h2>
<form>
<input type="text" name="name" id="name_input" list="huge_list">Name
<datalist id="huge_list">
</datalist>
<br/>
<input type="submit">
</form>
</body>
</html>
What we will do, is we will check whenever the user types into our field and then populate the datalist element with only what is necessary. Comments have been added to the code
index.js
window.addEventListener("load", function(){
// Add a keyup event listener to our input element
var name_input = document.getElementById('name_input');
name_input.addEventListener("keyup", function(event){hinter(event)});
// create one global XHR object
// so we can abort old requests when a new one is make
window.hinterXHR = new XMLHttpRequest();
});
// Autocomplete for form
function hinter(event) {
// retireve the input element
var input = event.target;
// retrieve the datalist element
var huge_list = document.getElementById('huge_list');
// minimum number of characters before we start to generate suggestions
var min_characters = 0;
if (input.value.length < min_characters ) {
return;
} else {
// abort any pending requests
window.hinterXHR.abort();
window.hinterXHR.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// We're expecting a json response so we convert it to an object
var response = JSON.parse( this.responseText );
// clear any previously loaded options in the datalist
huge_list.innerHTML = "";
response.forEach(function(item) {
// Create a new <option> element.
var option = document.createElement('option');
option.value = item;
// attach the option to the datalist element
huge_list.appendChild(option);
});
}
};
window.hinterXHR.open("GET", "/query.php?query=" + input.value, true);
window.hinterXHR.send()
}
}
On the server, we will listen and return a JSON formatted array of values. An example PHP script is.
query.php
<?php
$query = $_GET['query'];
// These values may have been gotten from a database.
// We'll use a simple array just to show this example.
$values = ['Neo',
'Ibiyemi',
'Olayinka',
'Jonathan',
'Stephen',
'Fisayo',
'Gideon',
'Mezie',
'Oreoluwa',
'Jordan',
'Enkay',
'Michelle',
'Jessica'];
if ($query) {
foreach ($values as $key => $value) {
if (stripos($value, $query) === false) {
unset($values[$key]);
}
}
}
echo json_encode(array_values($values));
?>
A problem with this method is that there is no default way to make sure that the input is from the list. To solve this, we will set a custom function for the submit action, and prevent submission if the value of the input is not found in the list.
IN
index.html
change
<h2>The form</h2>
<form>
<input type="text" name="name" id="name_input" list="huge_list">Name
to
<h2>The form</h2>
<form onsubmit="return validateForm()">
<input type="text" name="name" id="name_input" list="huge_list">Name
IN
index.js
add
function validateForm(){
// Get the input element
var input = document.getElementById('name_input');
// Get the datalist
var huge_list = document.getElementById('huge_list');
// If we find the input inside our list, we submit the form
for (var element of huge_list.children) {
if(element.value == input.value) {
return true;
}
}
// we send an error message
alert("name input is invalid")
return false;
}
That's all!!!
Now if the user tries to submit an invalid name, he will be shown an error message.
All sample code can be found in this GitHub repository
Part 1: Setting up using React Native and Expo Part 2: Ditching Expo Part 3: Adding authentication with firebase So, for my next project, I’ve de...
8 min read
Serverless deployment, the intriguing topic grabbing a lot of attention from rookies and veterans alike in the tech ecosystem is finally here. In th...
1 min read
Comments