Preview Your Images Instantly Before Uploading.
Tags: webdev, javascript, frontend, programming
Published: 2024-07-06 18:01:07

We all have used modern websites where you get the pleasure of previewing the image you have selected for upload before you send it to the server. Image preview is such an interesting experience to have as user. You have seen this several times on social media. This is a common experience in most modern websites.

As upcoming developers, we only get to see the default behavior when uploading files, that is an ugly display of the name of the image file alongside an ugly button that says 'Choose a file'. Now are you eager to find out what magic the developers of your favorite social media sites perform to make you happy about your pictures before sending them to the rest of the world? Yes, and this article will show you how to preview images on your websites before uploading. Perhaps you can also make the users of your websites as happy as you always are.

## Writing the Markup code
Previewing files is a such an easy task that we can accomplish with just about four lines of code. Before we go deeper into the magic of previewing the image, let us write some simple HTML code for selecting an image from your computer. 

```
<style>
    *{
        font-family: sans-serif;
    }
    body{
        text-align: center;
        padding-block-start: 4rem;
    }
    button{
        background-color: #0369a1;
        color: #f1f5f9;
        border-radius: 4px;
        padding-inline: 1rem;
        padding-block: .5rem;
        border: none;
    }

    button:hover{
        opacity: .7;
        transition: all .75s;
    }

    input{
        display: none;
    }
</style>
<body>
    <h1>Preview Before Upload</h1>
    <input type="file" name="imageFile">
    <button>Select Image</button>
</body>
```

The code snippet above renders a heading, a HTML input element for a file and a button named 'Select Image'. We have also included some CSS styles to improve the look and feel. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vl73kvomxurq3majqknp.png)

In the styles we have set the display property for the input element to none. Another unusual thing we have done is adding a button called 'Select Image'. Wondering why we have done this? For one reason, the default file selection component has an ugly display graphic so we can hide it from display and use something easier to style as a button. Another reason why we have used the button is to trigger file selection dialog even if we do not have the input element on display. This means that the input element is only hidden from display but its very much active.

## Selecting the file

The next thing we want to do is to give the button the ability to open the file selection dialog when clicked. Guessed how we are going to open the file input dialog using the button. Yes, you are right - by attaching a click event listener to the button. Well, that's true but what are we going to ask the browser in the event handler? Under default display conditions, we would click the file input element manually to open a file selection dialog. In this case we are going to ask the browser to click the file input element when the button is clicked. Once the event handler is executed the file input dialog for will be opened for us. Sounds brilliant, like an automation task, doesn't it? Enough with the words, let's implement what we have just said.

```
<script>
    const button  = document.querySelector('button')
    const fileInput = document.querySelector('input')

    button.addEventListener('click', () =>{
        fileInput.click()
    })
</script>
```

That's it, we have instructed the browser to open the file input dialog when the 'Select Image' button is clicked. We click the button which has the click even handler. The click even handler clicks the input element. The input element opens the file selection dialog on for us. The screenshot below shows how the result would look like. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t8q19wxq8tkrorinqvb3.png)

Right now if we select a file from the input dialog, we don't see anything on the screen. That sucks, let see how to preview the image in the next section.

## Displaying the Preview

Previewing an image on the client side requires one Browser API called the `FileReader`. The `FileReader` is provided readily to us by JavaSript. The `FileReader` allows us to asynchronously read content of a file in a way that can be displayed instantly. In the case of images, as data URL.

The task we have here is to tell the browser to load the fil and render it instantly after loading. How are we going to do this ? Have you ever heard of a `change` event? We can watch for the change event in the file input element, then do something when a file is selected. 

Let's start small, addi a `change` event listener to the input element.

```
fileInput.addEventListener('change', (event) =>{
        //Do something here
   })
```

Next we will wait for the file to be loaded into the browser then get the image URL before trying to display it. 

The code snippet below implements the task described above.

```
fileInput.addEventListener('change', (event) =>{
        
        //Get the file from files array
        const file = event.target.files[0]

        if(file){
            const fileReader = new FileReader() 

     //Set up event listener to the fileReader before begining to read
            fileReader.onloadend = () => {

                //Save the value read by the file reader in a variable
                const imageSrc = fileReader.result
            }

            // Tell the fileReader to read this file as URL
            fileReader.readAsDataURL(file) 
        }

    })
```

We now have a URL (`imageSrc`) that we can use to render an image. To render an image we need an `<img>` element. We can create an image element using the `createElement` method of the `document` library. After creating the `<img>` element we can use it to display the image we have just loaded into the browser.

```
 fileInput.addEventListener('change', (event) =>{
        
        //Get the file from files array
        const file = event.target.files[0]

        if(file){
            const fileReader = new FileReader() 

            fileReader.onloadend = () => {

                const imageSrc = fileReader.result
               
             // Create image element
                const img = document.createElement('img')

            // Assign value to the src attribute of the img element
                img.src = imageSrc

           // Add the image element to the body of the document
                document.body.appendChild(img)
            }

            fileReader.readAsDataURL(file) 
        }

    })
```

The code snippet added above enables us to preview before we can send it to the backend for storage. We created an image element,, assigned an image URL to it and rendered it. The image will be displayed instantly after selecting the file.

An example of what we meant to achieve looks like the following screenshot:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ivrvexjbcsx912uonnjq.png)


It looks like we have achieved what we wanted but we have a little problem. Have you tried selecting a second image? If you did then you must have realized that multiple images are displayed instead of the latest only. In this little experiment, we expect a new image to replace the existing image. 

## Preventing multiple image renders.
The solution to rendering multiple images involves cleaning up the DOM every time we are rendering a new image. We clean up to ensure that there is no other image in the body of the document that we don't intend to display. 

The following code snippet finds and removes an `<img>` element if it exists in the body of the document.

```
... //the rest of the change event handler code
 fileReader.onloadend = () => {

                //Save the value read by the file reader in a variable
                const imageSrc = fileReader.result



                //try to select the img tag
              const existingImgElement = document.querySelector('img')

 //Check if the tag is not null, it then remove it before rendering the next
                if(existingImgElement){
                    document.body.removeChild(existingImgElement)
                }



                const img = document.createElement('img')
                img.src = imageSrc
                document.body.appendChild(img)
            }

...//The rest of the change event handler code
```
In the above code snippet, we remove an `<img>` tag from the body of the document just before creating a new one. We check if the value of the existing image element is truthy to avoid potential errors. Removing the existing `<img>` tag from the body fixes the unintended rendering of multiple images.

Finally, we have successfully learned how to preview an image instantly before uploading. Such a little improvement on your web apps can do a lot good to the user experience on your web apps. Previewing an image before upload can be done using the `FileReader` API provided by JavaScript. A `loadend` event handler can be added the `FileReader` to to render the image after complete loading. The `FileReader` reads the image as a data URL. The result of the file reader can be assigned directly to the `src` attribute of the `img` tag to display the image instantly after selecting it.