skip to Main Content

I’m trying to create a form where you can upload multiple images using two file inputs, see the images as base64 and later submit them using jQuery’s POST. The problem is that when I select 3 different images, I see only the last one 3 times. I guess the problem is in the for in the addEventListener – maybe it’s not in the right place?

<div class="form-group">
    <label for="product_photo_1">Photos 1</label>
    <div class="custom-file">
        <input type="file" class="custom-file-input" id="product_photo_1" multiple />
        <label class="custom-file-label" for="product_photo_1" data-browse="Select">Please, select a file...</label>
    </div>
    <div id="product_photo_1_result"></div>
</div>
<div class="form-group">
    <label for="product_photo_2">Photos 2</label>
    <div class="custom-file">
        <input type="file" class="custom-file-input" id="product_photo_2" multiple />
        <label class="custom-file-label" for="product_photo_2" data-browse="Select">Please, select a file...</label>
    </div>
    <div id="product_photo_2_result"></div>
</div>
<script>
    const convertBase64 = (file) => {
        return new Promise((resolve, reject) => {
            const fileReader = new FileReader();

            fileReader.readAsDataURL(file);

            fileReader.onload = () => {
                resolve(fileReader.result);
            };

            fileReader.onerror = (error) => {
                reject(error);
            };
        });
    };

    const uploadImage = async (event, id) => {
        const file = event.target.files[0];

        const base64 = await convertBase64(file);

        document.getElementById("product_photo_" + id + "_result").innerHTML += '<img src="' + base64 + '" class="img-thumbnail m-2" id="product_photo_' + id + '[]" style="height: 50px;" />';
    };

    document.getElementById("product_photo_1").addEventListener("change", (event) => {
        for(var index = 1; index <= document.getElementById("product_photo_1").files.length; index++) {
            uploadImage(event, 1);
        }
    });

    document.getElementById("product_photo_2").addEventListener("change", (event) => {
        for(var index = 1; index <= document.getElementById("product_photo_2").files.length; index++) {
            uploadImage(event, 2);
        }
    });
</script>

2

Answers


  1. In uploadImage function you are passing event argument and select first file every time

    const file = event.target.files[0];
    

    Instead you can pass files one by one to the uploadImage.

    Here is the example:

    <div class="form-group">
      <label for="product_photo_1">Photos 1</label>
      <div class="custom-file">
        <input type="file" class="custom-file-input" id="product_photo_1" multiple />
        <label class="custom-file-label" for="product_photo_1" data-browse="Select">Please, select a file...</label>
      </div>
      <div id="product_photo_1_result"></div>
    </div>
    <div class="form-group">
      <label for="product_photo_2">Photos 2</label>
      <div class="custom-file">
        <input type="file" class="custom-file-input" id="product_photo_2" multiple />
        <label class="custom-file-label" for="product_photo_2" data-browse="Select">Please, select a file...</label>
      </div>
      <div id="product_photo_2_result"></div>
    </div>
    <script>
      const convertBase64 = (file) => {
        return new Promise((resolve, reject) => {
          const fileReader = new FileReader();
    
          fileReader.readAsDataURL(file);
    
          fileReader.onload = () => {
            resolve(fileReader.result);
          };
    
          fileReader.onerror = (error) => {
            reject(error);
          };
        });
      };
    
      const uploadImage = async (file, id) => {
      
        const base64 = await convertBase64(file);
    
        document.getElementById("product_photo_" + id + "_result").innerHTML += '<img src="' + base64 + '" class="img-thumbnail m-2" id="product_photo_' + id + '[]" style="height: 50px;" />';
      };
    
      document.getElementById("product_photo_1").addEventListener("change", (event) => {
       let files = document.getElementById("product_photo_1").files;
        for (let index = 0; index <= files.length; index++) {
          uploadImage(files[index], 1);
        }
      });
    
      document.getElementById("product_photo_2").addEventListener("change", (event) => {
        let files = document.getElementById("product_photo_2").files;
        for (let index = 0; index <= document.getElementById("product_photo_2").files.length; index++) {
          uploadImage(files[index], 2);
        }
      });
    
    </script>
    Login or Signup to reply.
  2. In the event handlers, you are doing a loop, but you are not using the value of index per iteration:

        document.getElementById("product_photo_1").addEventListener("change", (event) => {
            for(var index = 1; index <= document.getElementById("product_photo_1").files.length; index++) {
                uploadImage(event, 1); //passing only the event and an index
            }
        });
    
        document.getElementById("product_photo_2").addEventListener("change", (event) => {
            for(var index = 1; index <= document.getElementById("product_photo_2").files.length; index++) {
                uploadImage(event, 2); //passing only the event and the index
            }
        });
    
    And now, let's use `index` for all calls as well as clearing up when it's 0:
    
    
    const uploadImage = async (event, id, index) => {
        let context = document.getElementById("product_photo_" + id + "_result");
        const file = event.target.files[index]; //we get the correct file;
    
        const base64 = await convertBase64(file);
    
        let template = '<img src="' + base64 + '" class="img-thumbnail m-2" id="product_photo_' + id + '[]" style="height: 50px;" />';
    
        if (index === 0) context.innerHTML = template; //clearing older values and adding the first element
        else context.innerHTML += template; //appending the (not first) element
    };
    

    Instead, you will need to pass the index as well, like this:

        document.getElementById("product_photo_1").addEventListener("change", (event) => {
            for(var index = 0; index < document.getElementById("product_photo_1").files.length; index++) {
                uploadImage(event, 1, index);
            }
        });
    
        document.getElementById("product_photo_2").addEventListener("change", (event) => {
            for(var index = 0; index < document.getElementById("product_photo_2").files.length; index++) {
                uploadImage(event, 2, index);
            }
        });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search