0

I have a maintenance event which may have 0 or n amount of products. In my Create Maintenance event, I have a button which adds products using EditorForMany extension. For every product, there is a select list to pick the product. I want to have a readonly field for the selected product called Units. Units is defined for each product in database as "mt", or "mm", "number".

Every time I select a product, it should update the unit reading from database BUT instead it tries to update the first product's unit.

I'm doing something wrong with Selectors ( I guess ). But I really can't put my finger on it.

In my view

@model Models.Maintanance.AddMaintananceVM
<form asp-action="BakimIsle" autocomplete="off">
<label asp-for="Date" class="control-label"></label>
            <div class="input-group">
                <input asp-for="Date" type="text" class="form-control" >
                <div class="input-group-append">
                    <span class="input-group-text"><i class="ion-calendar"></i></span>
                </div>
            </div>
 <div id="parts-list">
    @Html.EditorForMany(x => x.Parts, x => x.Index, false)
</div>
<input type="button" id="add-part" class="btn btn-outline-primary waves-effect waves-light btn-sm" value="Add" />
<button type="submit" class="btn btn-primary">Kaydet</button>

<script>
    $(document).ready(function () {

        $('#add-part').on('click', function () {
            jQuery.get('@Url.Action("AddPart")').done(function (html) {
                $('#parts-list').append(html);

            });
        });

        $("#parts-list").on('change',"#Product", function () {
            LoadProductsData($("#Product option:selected").val());
        });

        $(document).on('click', '.delete', function () {
            $(this).closest('.partRow').remove();
        });

    });
</script>

I believe my problem is here...Function called LoadProductsData is working and getting the correct data from controller but it's trying to update ONLY the first entered product's Unit.

<script>
    function LoadProductsData(id) {
        $('#Unit').val('');
        $.ajax({
            type: "GET",
            url: "@Url.Action("LoadProductById")",
            datatype: "Json",
            data: { productId: id },
            success: function (data) {
                $.each(data, function (index, value) {
                    $("#Unit").val(value.units);

                });

            }
        });
    }
</script>

View For EditorForMany

@model Models.Maintanance.PartVM

<div class="partRow">
<div class="card-box">
    <div class="row">
        <div class="col-md-2">
            <label asp-for="PartId" class="control-label"></label>
            <select asp-for="PartId" asp-items="Model.AllParts" id="Product" 
class="form-control">
                <option value="">Parça seç</option>
            </select>
        </div>
        <div class="col-md-2">
            <label asp-for="AmountOfPart" class="control-label"></label>
            <input asp-for="AmountOfPart" class="form-control" />
        </div>
        <div class="col-md-2">
            <label asp-for="Units" class="control-label"></label>
            <input asp-for="Units" class="form-control" id="Unit" readonly 
/>
        </div>
        <div class="col-md-2">
            <input type="button" class="btn btn-outline-primary waves-effect 
waves-light btn-sm delete" value="Sil" style="align-items:baseline" />
        </div>
    </div>
</div>
</div>

My ViewModels

public class AddMaintananceVM
{
    public AddMaintananceVM()
    {
        Parts = new List<PartDetailsVM>();
    }

    [DataType(DataType.Date)]
    public DateTime Date { get; set; }
    public List<PartDetailsVM> Parts { get; set; }
}
 public class PartDetailsVM
{
    public int PartId { get; set; }
    public int AmountOfPart { get; set; }
    public string Units { get;  }
    public string Index { get; set; }
    public IEnumerable<SelectListItem> AllParts { get; set; }
}

My Controller

    public IActionResult BakimIsle()
    {
        var model = new AddMaintananceVM();
        model.Date = DateTime.Now;
        model.MonthOfMaintanance = DateTime.Now.Month;
        var elevators = _maintananceService.GetAllOnMaintanance();
        var employees = _employeeService.GetAllForMaintanance();
        var products = _productService.GetAllForMaintanance();

        model.Elevators = new SelectList(elevators, "Id", "PublicName");
        model.Employees = new SelectList(employees, "Id", "FullName");

        model.Parts = new List<PartDetailsVM>()
        { new PartDetailsVM() { AllParts= new SelectList(products , "Id", "Name")} };

        return View(model);
    }

    [Route("bakim/bakimisle")]
    [HttpPost]
    public IActionResult BakimIsle(AddMaintananceVM model)
    {
        var maintanance = new Maintanance()
        {
            Date = model.Date,
        };
        _maintananceService.AddMaintanance(maintanance);

        _maintananceService.Complete();
        return RedirectToAction("Index");
    }


    public IActionResult AddPart()
    {
        var products = _productService.GetAllForMaintanance();

        var model = new AddMaintananceVM();
        model.Parts = new List<PartDetailsVM>()
        { new PartDetailsVM() { AllParts= new SelectList(products, "Id", "Name")} };

        return View(model);
    }
    public JsonResult LoadProductById(int productId)
    {
        var product= _productService.GetAllForMaintanance().Where(x=> x.Id == productId);

        return Json(product);
    }

It would be great if you can help me fix the code.

EDIT

Thanks to Taplar in comments section. Trying to fix the code..

These are the code I changed. Basically making Id's into Classes.

 $("#parts-list").on('change',".partRow .product", function () {
            LoadProductsData($(".product option:selected").val());
        });

and

function LoadProductsData(id) {
        $(this).closest('.partRow').find('.unit').val('');
        $.ajax({
            type: "GET",
            url: "@Url.Action("LoadProductById")",
            datatype: "Json",
            data: { productId: id },
            success: function (data) {
                $.each(data, function (index, value) {
                    $(this).closest('.partRow').find('.unit').val(value.units);
                });
            }
        });
    }

These are the changes I made. Still have some errors and I really can't figure out what. $(this).closest('.partRow').find('.unit').val(value.units) is not finding anything.

Pumpkin
  • 1
  • 2
  • Possible duplicate of [Does ID have to be unique in the whole page?](https://stackoverflow.com/questions/9454645/does-id-have-to-be-unique-in-the-whole-page) – Taplar Mar 21 '19 at 21:56
  • Id's cannot repeat. Repeatedly calling a selector on a single id, is not going to auto-advance to the next one with the same id. There should only be one element with a given id on the entire page. You want to use a class instead paired with some logic that knows which index of the class to change. – Taplar Mar 21 '19 at 21:56
  • Yes that makes a lot of sense. How can I work around it? For example, my $(document).on('click', '.delete', function () {$(this).closest('.partRow').remove(); }); works perfectly fine. Is there a way I can use something like this for getting Unit ? – Pumpkin Mar 21 '19 at 22:26
  • Yeah, using contextual selectors like that is definitely the way to go, if you want to manipulate things dependent upon which element is being acted upon. – Taplar Mar 21 '19 at 22:28
  • `$(this).closest('.partRow').find('.unit')`. Navigating the DOM tree like that, you can find whatever you want, :) – Taplar Mar 21 '19 at 22:29
  • @Taplar Thanks a lot for the answers! I feel I'm closer now :) Made some edits. Still can't get it to work – Pumpkin Mar 21 '19 at 23:58

0 Answers0