Animate Loading Indicator on Button With Vanilla Javascript
Tags: javascript, css, html, beginners
Published: 2022-08-25 22:19:58

Hi there 🙋🏾‍♂️,

In today's post, we are making a loading indicator on a submit button. This is a common feature nowadays to display/hide spinner on a button while application is in a busy state. I did this at a very basic level i.e. without any complicated code. There are several ways to do this. Please do not hesitate to share them with us 😊.

Basic skills in HTML, CSS and Javascript will be just fine to follow this post.

To the coding part, we will only need 3 files;
- index.html
- style.css
- main.js

Start by creating an html boiler plate:

###### _index.html_
```
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Loading Indicator</title>
</head>
<body>
    
</body>
</html>
```
Next we bring in our css and javascript files into the index.html;

###### _index.html_
```
    <link rel="stylesheet" href="style.css" />
    <script src="main.js" defer></script>
```

To get a feel of submitting a data, we will create a dummy form and add two input elements and a submit button even though we will not submit any data.

###### _index.html_
```
    <form class="sampleForm">
      <h1>Login form</h1>
      <div>
        <input type="text" placeholder="Enter email" />
      </div>
      <div>
        <input type="password" placeholder="Enter password" />
      </div>
      <button id="btnSubmit">
        <span id="btnSubmitText">Submit</span>
      </button>
    </form>
```

From the code we just added, we have a;
- form with an id of **sampleForm**
- 2 input elements ( a text and a password type both with placeholders)
- a submit button with a child span element with an id of **btnSubmitText**

At this point we will use [fontawesome](https://fontawesome.com)'s spinner icon. We include the cdn but you can also download the kit and set it up manually if you are familiar with the process.

###### _index.html_
```
<!-- Fontawesome cdn -->
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css"
   integrity="sha512-1sCRPdkRXhBV2PBLUdRb4tMg1w2YPf37qatUFeS7zlBy7jJI8Lf4VHwWfZZfpXtYSLy85pkm9GaYVYMfw5BC1A=="
      crossorigin="anonymous"
      referrerpolicy="no-referrer"
    />
```

We will now add two child elements in the buttom: the fontawesome's spinner icon and span element as below;

###### _index.html_
```
<button id="btnSubmit">
  <span id="btnSubmitText">Submit</span>
  <i class="fa-solid fa-spinner fa-spin"></i>
</button>
```
The **fa-spinner** class adds the spinner icon and to animate the icon, we add **fa-spin** class. There are other animations like **beat, fade, bounce, shake,** etc, all at [fontawesome animation](https://fontawesome.com/docs/web/style/animate). 

Next we add some styles to our form.

###### _style.css_
```
.sampleForm {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
}
input {
  padding: 10px;
  margin: 5px;
  width: 250px;
}
button {
  background-color: orange;
  color: white;
  border: none;
  font-size: 20px;
  padding: 10px;
  width: 150px;
  height: 50px;
  cursor: pointer;
}
.fa-spinner {
  display: none;
}

```
The button has a fixed width and height. This is to maintain the same button size when we toggle the icon and text. Initially we are hiding the icon and showing the text on the button. When we click on the button, the text will be set to `display:none` and the icon will be set `display:block`. Let's do that right now.

In the `main.js` file, add the following code

###### _main.js_
```
const btnSubmit = document.getElementById('btnSubmit')

btnSubmit.addEventListener('click', (event) => {
  event.preventDefault()

})
```
So we grab the submit button and assign it to `btnSubmit` then listen to the `click` event on the submit button. By default, a submit form button causes a web page to refresh each time it is clicked. To prevent that, we pass the `event` argument to the callback function and called the `preventDefault()` function of the `event` object. 

Now when the button is clicked, we want to hide the text (which is currently displayed) and display the spin icon (which is currently hidden). Let's write that code

###### _main.js_
```
  //Hide the text
  document.getElementById('btnSubmitText').style.display = 'none'

  //Display the spin icon
  document.querySelector('.fa-spinner').style.display = 'block'
```

Our code targets the span element that contains the text by id and assign the display property of it's style object to `none` which causes it to hide. On the hand, the icon is now displayed by setting it display property to `block`.

At this point, when we click the submit button, the submit text will hide and the spin icon will display.

Phewwwww...now that was a lot and you deserve the applause 🎉🙌🏽🍾🥳🥳🎉🎉🙌🏽
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dhuf51q7pxirzm8z3dg0.gif)

But we are not quite done yet. Our spin icon keeps spinning until we refresh the page and obviously we don't want that. 
Normally when we send a form request, we expect a response and after the response, our button text should display and spin icon hidden. 

To do that, we just do reverse of our code as below;

###### _main.js_
```
  document.getElementById('btnSubmitText').style.display = 'block'
  document.querySelector('.fa-spinner').style.display = 'none'
```
Now after adding this code, it happens so fast that we don't see the spin icon right? We can fake a request/response by adding a delay of 2 seconds using the `setTimeout` function.

Our `main.js` file will now look like this;

###### _main.js_
```
const btnSubmit = document.getElementById('btnSubmit')

btnSubmit.addEventListener('click', (event) => {
  event.preventDefault()

  //Hide the text
  document.getElementById('btnSubmitText').style.display = 'none'

  //Display the spin icon
  document.querySelector('.fa-spinner').style.display = 'block'

  //2 seconds delay
  setTimeout(() => {
    //Show the text after 2 seconds
    document.getElementById('btnSubmitText').style.display = 'block'

    //Hide the spin icon after 2 seconds
    document.querySelector('.fa-spinner').style.display = 'none'
  }, 2000)
})

```
 
As I mentioned earlier, this is just for basic level coding but you can definitely make this code better. Think of how you can make it reusable by introducing functions in the code.

You can download the files from my [github repo](https://github.com/momokid/loading_indicator). Please don't forget to leave a like 👍🏼.

Thanks for spending time to read and see you on the next one.