Reading:
Autocomplete Live AJAX Example without jquery

Autocomplete Live AJAX Example without jquery

Metamug
Autocomplete Live AJAX Example without jquery

Motivation

I searched for a standard solution for creating autocomplete input field. To my surprise, there were good no pure javascript solutions. I tried an autocomplete libary, but couldn't get it to work for ajax calls. It required data to be prefetched. So I ended up writing my solution, which worked on live ajax calls.

In the below approach, we will handle the following problems.

  1. How to call ajax on input keyup
  2. Add ajax search result to autocomplete dropdown
  3. Clear Autocomplete Dropdown

HTML

We can add this section anywhere on the page. The below section can be added inside an HTML form element. The autocompleted value will be sent in the form submit, as it is an input field. The form can be submitted using ajax or through a regular POST server call.

<section class="control" id="searchbox-container">
    <input class="input is-dark" type="text" name="city" placeholder="Where were you born?" id="searchbox" autocomplete="off" />
    <div class="control" id="dropdown-menu"></div>
</section>

Calling ajax on keyup

When calling ajax on keyup, use a timeout function to not immediately send the ajax call. Another important check is DO NOTHING when input box is empty.

const searchBox = document.getElementById('searchbox');
const dropdownMenu = document.getElementById('dropdown-menu');
const searchBoxContainer = document.getElementById('searchbox-container');

searchBox.addEventListener("keyup", function(event) { 

    const timer = setTimeout(function () { 
        var sr = event.target.value;
        if(!sr) return; //Do nothing for empty value
        searchBoxContainer.classList.add("control", "is-loading");

        const request = new Request('https://api.metamug.com/covid/v1.1/city?q='+sr+'&limit=7');
        fetch(request)
            .then((response) => response.json())
            .then((data) => {
                if (searchBox.value) { //src not cleaned, backspace removed
                    dropdownMenu.replaceChildren(searchResult(data));
                }
                searchBoxContainer.classList.remove("is-loading");  
            });

    }, 500);
});

In each ajax response, we will remove all the fields and add the ajax response. Instead of using dropdownMenu.innerHTML='' along with appendChild, we have used replaceChildren as it is native API available

API Details

Below API is available, which has been used for this example.

https://api.metamug.com/covid/v1.1/city?q=mumbai&limit=7

Add ajax search result to autocomplete dropdown

The dropdown is an unordered list ul with each record as li. In this code we have avoided using data- attributes and added events on each of the li elements.

function searchResult(result){

    const ul = document.createElement('ul')
    ul.classList.add('box', 'mt-1' );

    const loc = result.loc1.concat(result.loc2);
    loc.forEach((x)=>{
        if(!x)return;
        ul.appendChild(createListItem(x))
    })

    return ul;
}

Since we are adding an event on each of the elements in the dropdown, we must disable event propogation to avoid event bubbling to its parents.

function createListItem(x){

    const li = document.createElement('li') 
    li.classList.add('py-1'); //, 'pl-5', 'is-capitalized')
    //li.dataset.lat = x.lat;
    //li.dataset.lon = x.lon;
    //li.dataset.tz = x.tz;
    li.innerText = x.name

    const selectEvent = function(event){
        event.stopPropagation(); //parent elements will not have the same event 
        const li = event.target
        clearDropdown();
        searchBox.value = x.name;
    };

    li.addEventListener('click', selectEvent)
    li.addEventListener('touchstart', selectEvent)

    return li
}

Along with the click event, a touch event is also added for mobile devices.

Clear Dropdown

Do clear the dropdown, when the input box is empty. setInterval here is used to keep checking for the input box for blank.

function clearDropdown(){
    //dropdownMenu.replaceChildren(); https://stackoverflow.com/a/65413839/1097600
    dropdownMenu.innerHTML = '';
    searchBoxContainer.classList.remove("is-loading");
}

//keep checking for an empty search box every 5 seconds
setInterval(function() {
    if (!searchBox.value) { //empty search box
        clearDropdown()
    }
}, 500);

You can find the complete Autocomplete JS code here.

Required CSS

.control {
    box-sizing: border-box;
    clear: both;
    font-size: 1rem;
    position: relative;
    text-align: inherit;
}

.mt-1 {
    margin-top: 0.25rem!important;
}

.box {
    background-color: #fff;
    border-radius: 6px;
    box-shadow: 0 0.5em 1em -0.125em rgb(10 10 10 / 10%), 0 0 0 1px rgb(10 10 10 / 2%);
    color: #4a4a4a;
    display: block;
    padding: 1.25rem;
}

ul {
    list-style: none;
}

.input, .textarea {
    box-shadow: inset 0 0.0625em 0.125em rgb(10 10 10 / 5%);
    max-width: 100%;
    width: 100%;
}

.control.is-loading::after {
 position:absolute!important;
 right:.625em;
 top:.625em;
 z-index:4
}


Icon For Arrow-up
Comments

Post a comment