How to use file option for each elements of list, and pass its value into controllers using jQuery

Viewed 95

I am at beginner level for using Jquery.

Problem : so the problem is that, I have to add "choose file" for each of the element's inside a tag. And display the image after selecting it inside the tag. But Has this is this list of elements using for each loop, it cannot different between the id property. please see the images and code for reference and help me out, Thank You !!!

[.cshtml]
@if (Model.DailyMenuProducts != null && Model.DailyMenuProducts.Count > 0)
{
@for (int i = 0; i < Model.DailyMenuProducts.Count; i++)
{
 <li class="list-group-item">
    <input asp-for="@Model.DailyMenuProducts[i].IsChecked" type="checkbox" />
    <label asp-for="@Model.DailyMenuProducts[i].ProductId">  @Model.DailyMenuProducts[i].ProductName</label>
    <input type="hidden" asp-for="@Model.DailyMenuProducts[i].ProductId"/>
    <input type="hidden" asp-for="@Model.DailyMenuProducts[i].ProductName" asp-route-productId/>
        <div  class="uploadFile float-end">
            <label for="productImage">
                <img id="imageViewer" width="50" height="50" style="border: 1px solid #000000; cursor:pointer;" />
            </label>
            <input asp-for="@Model.DailyMenuProducts[i].ProductImage" asp-for-ProductId="@Model.DailyMenuProducts[i].ProductId" type="file" id="productImage" style="display:none; visibility:none" onchange="getImage(this.value);"/>
         </div>
</li>
}

[.js]

$(".uploadFile").on('change', function () {
        console.log('new file uploaded')
        //var array = $("#productImage").getIdArray();
        var file_data = $("#productImage").prop("files")[0];
        var files = event.target.files
        $("#imageViewer").attr("src", window.URL.createObjectURL(files[0]));
        var form_data = new FormData();
        var product_Id = (this.ProductId) ;
        var viewModel = { ProductId: product_Id, ProductImage: file_data};
        form_data.append("file", file_data);
        $.ajax({
            url: "/DailyMenuPlanner/AddPhoto",
            cache: false,
            contentType: false,
            processData: false,
            data: viewModel,
            type: 'post',
            success: function (result) {
                if (result.success == true) { alert("success!"); }
                else { alert("fail!"); }
            }
        });
        
    });

In this image you can see that each elements have choose file option, and i have selected image for the first one and so the image is reflecting there! but if i select image for 2nd element then it effect only for 1st element and image of 1st element will change not for the 2nd element

After applying the suggestion by @JerdineSabio & replaced 'id' with 'class' now each element getting image separatly but i want to use as file input

Label Click event trigger but doesn't opens the file input

1 Answers

HTML id attribute should be unique. In your code, only the first element with id=productImage is being replaced.

What you could do is use $(this).find(selector). This will find the element inside the current element.

In the code below, the current element is .uploadFile and .find() will search inside that element.

$(".uploadFile").on("change", function () {
   var file_data = $(this).find("#productImage").prop("files")[0];
   ...
   $(this).find("#imageViewer").attr("src", window.URL.createObjectURL(files[0]));
   ...
}

If the above code doesn't work, just replace the id with classes;

<img class="imageViewer" width="50" height="50" style="border: 1px solid #000000; cursor:pointer;" />
<input class="productImage" asp-for="@Model.DailyMenuProducts[i].ProductImage" asp-for-ProductId="@Model.DailyMenuProducts[i].ProductId" type="file" style="display:none; visibility:none" onchange="getImage(this.value);"/>

Then in your script, use the class name instead of id;

$(".uploadFile").on("change", function () {
   var file_data = $(this).find(".productImage").prop("files")[0];
   ...
   $(this).find(".imageViewer").attr("src", window.URL.createObjectURL(files[0]));
   ...
}

If you want to use your label as file input, you could add a click event to your label that triggers the click on your input field.

// add file-label to your class
<label class="file-label"></label>

// add this script to your js file
$(".file-label").click(function(){
   var parent = $(this).parent();
   var target = $(parent).find(".productImage");
   $(target).click();
});
Related