Home > Software design >  Multiple image upload is not working javascript
Multiple image upload is not working javascript

Time:11-06

I want to create multiple upload images and preview sections, somehow I created one. The first one is working fine but not the second one. Please help me. Here is the code. <par-div\> is a custom HTML tag as I was facing an issue in Tabs.

JSFiddle Link.

 const wrapper = document.querySelector(".wrapper");
         const fileName = document.querySelector(".file-name");
         const defaultBtn = document.querySelector("#default-btn");
         const customBtn = document.querySelector("#custom-btn");
         const cancelBtnBg = document.querySelector("#cancel-btn");
         const cancelBtn = document.querySelector("#cancel-btn i");
         const img = document.querySelector("img");
         const image = document.querySelector(".image");
         function defaultBtnActive(){
           defaultBtn.click();
         }
         defaultBtn.addEventListener("change", function(){
           const file = this.files[0];
           if(file){
             const reader = new FileReader();
             reader.onload = function(){
               const result = reader.result;
               img.src = result;
               wrapper.classList.add("active");
               image.style.display='flex';
               cancelBtnBg.style.display='flex';
               defaultBtn.disabled = true;
               customBtn.disabled = true;
             }
             cancelBtn.addEventListener("click", function(e){
                e.preventDefault();
               img.src = "";
               wrapper.classList.remove("active");
               image.style.display='none';
               cancelBtnBg.style.display='none';
               defaultBtn.disabled = false;
               customBtn.disabled = false;
             })
             reader.readAsDataURL(file);
           }
         });
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">

<par-div >
         <label for="default-btn" >
            <par-div >
               <img src="" width="100px" alt="">
            </par-div>
            <par-div >
               <par-div >
                <i ></i>
               </par-div>
               <par-div >
                  upload Main
               </par-div>
            </par-div>
            <par-div id="cancel-btn">
                <i ></i>
            </par-div>
            <button onclick="defaultBtnActive()" id="custom-btn">Choose a file</button>
            <input id="default-btn" type="file" accept="image/*" multiple hidden>
        </label>
        <!-------->
        <label for="default-btn" >
            <par-div >
               <img src="" width="100px" alt="">
            </par-div>
            <par-div >
               <par-div >
                <i ></i>
               </par-div>
               <par-div >
                  upload Main
               </par-div>
            </par-div>
            <par-div id="cancel-btn">
                <i ></i>
            </par-div>
            <button onclick="defaultBtnActive()" id="custom-btn">Choose a file</button>
            <inpu
      </par-div>

CodePudding user response:

You have duplicated the HTML and the code, but the code now references selectors which will return more than one element. When querySelector encounters more than one matching element, it will just return the first one every time.

You need to loop over each .wrapper and scope all the selectors inside to the wrapper it's operating on.

Additionally, you need to remove the for HTML attribute as since the input/buttons are nested they are already related. This makes it more convenient because you do have some more problems in the HTML -- though only mostly about being HTML spec-compliant. You aren't supposed to have multiple elements on a page with the same ID. Because of that, you can't craft a for attribute to uniquely identify the right element -- however it does not matter as above, they are related anyway automatically if nested so the easiest workaround is to not use for at all.

You have duplicated id attributes though in a few places. Now there are two copies you should probably go further on my answer and change any ID selectors which don't actually uniquely identify an element to classes or data attributes.

I also moved the onclick attribute away and instead used addEventListener for that. It's easier when looping to do it like this as you already have a unique reference to the element being operated on. Otherwise you'd have to build out multiple different functions and pass different ones to each onclick.

HTML

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">

<par-div >
         <label >
            <par-div >
               <img src="" width="100px" alt="">
            </par-div>
            <par-div >
               <par-div >
                <i ></i>
               </par-div>
               <par-div >
                  upload Main
               </par-div>
            </par-div>
            <par-div id="cancel-btn">
                <i ></i>
            </par-div>
            <button id="custom-btn">Choose a file</button>
            <input id="default-btn" type="file" accept="image/*" multiple hidden>
        </label>
        <!-------->
        <label >
            <par-div >
               <img src="" width="100px" alt="">
            </par-div>
            <par-div >
               <par-div >
                <i ></i>
               </par-div>
               <par-div >
                  upload Main
               </par-div>
            </par-div>
            <par-div id="cancel-btn">
                <i ></i>
            </par-div>
             <button id="custom-btn">Choose a file</button>
             <input id="default-btn" type="file" accept="image/*" multiple hidden>
      </par-div>


document.querySelectorAll(".wrapper").forEach((wrapper) => {
         const fileName = wrapper.querySelector(".file-name");
         const defaultBtn = wrapper.querySelector("#default-btn");
         const customBtn = wrapper.querySelector("#custom-btn");
         const cancelBtnBg = wrapper.querySelector("#cancel-btn");
         const cancelBtn = wrapper.querySelector("#cancel-btn i");
         const img = wrapper.querySelector("img");
         const image = wrapper.querySelector(".image");
    
         function defaultBtnActive(){
           defaultBtn.click();
         }
         
         customBtn.addEventListener("click", defaultBtnActive)
         
         
         defaultBtn.addEventListener("change", function(){
           const file = this.files[0];
           if(file){
             const reader = new FileReader();
             reader.onload = function(){
               const result = reader.result;
               img.src = result;
               wrapper.classList.add("active");
               image.style.display='flex';
               cancelBtnBg.style.display='flex';
               defaultBtn.disabled = true;
               customBtn.disabled = true;
             }
             cancelBtn.addEventListener("click", function(e){
                e.preventDefault();
               img.src = "";
               wrapper.classList.remove("active");
               image.style.display='none';
               cancelBtnBg.style.display='none';
               defaultBtn.disabled = false;
               customBtn.disabled = false;
             })
             reader.readAsDataURL(file);
           }
         });
})
   


  • Related