jquery file browse adding and removing but not able to take file from other input tags except first

I want to apply a logic from which I can use give new generated class to new added element.

I want that whenever I click on Add Another, it will add new file browse and I can select different images from that. The first image should always be primary and others will be secondary. When I click on remove link, corresponding file browse and dropdown should be removed.

$(document).ready(function(){

    $(".browse").click(function(){
        $(".myfile").click(); 
    });

    $(".myfile").on('change', function() { 
        $(".path").val(this.files[0].name); 
    });

    $(".add").click(function(){
        $("form").append("<div>"+$("form div:first-child").html()+"<br>"+"</div>"); 
    });

    $(".remove").click(function(){
        $("form div:last-child").remove(); 
    });
});
.main{
    width: 100%;
}

.sub1{
    border: 2px solid #808080;
    padding-left: 10px;
}

.sub2{
    display: flex;
    border: 1px solid #808080;  
}


.child1{
    width: 20%;
    padding-left: 10px;
    border: 1px solid #808080;
}

.child2{
    width: 80%;
    padding: 10px;
    border: 1px solid #808080;
}

.add{
    cursor: pointer;
}

.upload1{
    display: none;
}

.browse{
    display: inline-block;
    width: 80px;
    height: 18px;
    background-color: #d3d3d3;
    color: #000;
    border: 1px solid black;
    border-radius: 2px;
    cursor: pointer;
}

.browsebut{
    margin-left: 16px;
}

.myf{
    position: absolute;     
}




/* position: absolute;
    opacity: 5;
    top: 74px;
    display: -webkit-box; */
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Browse</title>
    <!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script> -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    
    <div class="main">
        <div class="sub1">
            <p>Property Image</p>
        </div>
        <div class="sub2">
            <div class="child1">
                <p>Property Image</p>
            </div>
            <div class="child2">

               
                    <form>
                        <div class="upload">
                            <input type="text" name="path" class="path" value="no file selected">

                            <div id="browse" class="browse"><span class="browsebut">Browse</span></div>
                            <div class="myf"> 
                                <label for="myfile"></label>
                                <input type="file" class="myfile" name="myfile" accept="image/*" hidden >
                            </div>
                            <select id="img">
                                <option value="1">primary</option>
                                <option value="1">secondaryimg</option>
                            </select>

                            <a href="#" class="remove">Remove</a>
                        </div>        
                
                    </form>
                
                    
                
                <div class="add">
                    <p>Add Another</p>
                </div>
            </div>
        </div>    
    </div>[enter image description here][1]

    <script src="index.js"></script>
</body>
</html>

Answer

For what you’re trying to achieve, need to use event delegates. When new elements are dynamically added, the handlers added by the your original jQuery code is only aware of the first row’s elements, which is why none of the other row elements seemed to work after adding additional rows.

There were a couple of corrections applied:

  1. For the row elements, I removed all id attributes, for these need to be unique in the document.
  2. Both select options had value="1", so I set the secondaryimg option to value="2"
  3. Removed the unused label tag.

Other:

  1. Used placeholder with the first input to show the no file selected text.
  2. See the .add handler for the handling to set the select option to secondaryimg
  3. The remove event handler does not allow the primary (first element) to be removed. (feel free to eliminate the condition wrapping remove() if not needed)
  4. Having repeated elements with the same name is why only the first entry is retrieved. Now that there will be one or more rows, the name attributes for path, myfile and the select all need the array syntax, so that whenever you submit, you can easily iterate the list. The path input name attribute changes to name="path[]". The myfile input name attribute changes to name="myfile[], and the select did not have a name attribute, so I used name="imgOpt[]", feel free to rename as desired. At submit, the iteration of path[0], myfile[0], and imgOpt[0] all refer to the first row. Simply increase the index for the other rows.
  5. See the jquery code comments for the updated handling.

Try the runnable example below.

$(document).ready(function(){
    // Browse button event delegate
    $('form').on('click', '.browse', function(){
        // Fire click for myfile input on the SAME row
        $(this).next().find('input').click(); 
    });

    // Myfile change event delegate
    $('form').on('change', '.myfile', function() {
        // Copy the image to the path input on the SAME row.
        $(this).parent().siblings().first().val(this.files[0].name); 
    });

    $(".add").click(function(){
        $("form").append("<div>"+$("form div:first-child").html()+"<br>"+"</div>");
         // Set the added select to the 2nd (secondaryimg) option.
        $('select').last().val(2);
    });

    // Anchor tag event delegate
    $("form").on('click', 'a.remove', function() {
        if (!$(this).is($('a')[0])) { // Don't remove the first primary anchor tag?
            $(this).parent().remove();
        }
    });
});
.main{
    width: 100%;
}

.sub1{
    border: 2px solid #808080;
    padding-left: 10px;
}

.sub2{
    display: flex;
    border: 1px solid #808080;  
}


.child1{
    width: 20%;
    padding-left: 10px;
    border: 1px solid #808080;
}

.child2{
    width: 80%;
    padding: 10px;
    border: 1px solid #808080;
}

.add{
    cursor: pointer;
}

.upload1{
    display: none;
}

.browse{
    display: inline-block;
    width: 80px;
    height: 18px;
    background-color: #d3d3d3;
    color: #000;
    border: 1px solid black;
    border-radius: 2px;
    cursor: pointer;
}

.browsebut{
    margin-left: 16px;
}

.myf{
    position: absolute;     
}

/* position: absolute;
    opacity: 5;
    top: 74px;
    display: -webkit-box; */
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Browse</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    
    <div class="main">
        <div class="sub1">
            <p>Property Image</p>
        </div>
        <div class="sub2">
            <div class="child1">
                <p>Property Image</p>
            </div>
            <div class="child2">
                <form>
                    <div class="upload">
                        <input type="text" name="path[]" class="path" 
                               placeholder="no file selected" value="">

                        <div class="browse">
                            <span class="browsebut">Browse</span>
                        </div>
                        <div class="myf"> 
                            <input type="file" class="myfile" 
                                   name="myfile[]" accept="image/*" hidden>
                        </div>
                        <select name="imgOpt[]">
                            <option value="1">primary</option>
                            <option value="2">secondaryimg</option>
                        </select>
                        <a href="#" class="remove">Remove</a>
                    </div>        
                </form>
                <div class="add">
                    <p>Add Another</p>
                </div>
            </div>
        </div>    
    </div>

    <script src="index.js"></script>
</body>
</html>

Leave a Reply

Your email address will not be published. Required fields are marked *