Delayed execution of Javascript

In my project I have a modal window where a cascading dropdownlist is shown for two properties (Family, TypeID) of a class (Machine).

The issue: The dependant dropdownlist populates only when the modal window has been open for the second time. On the first time, nothing happens:

Here is a picture of how it works for a better understanding:

enter image description here

Notice that the row that says Modelo (Modelo is the name for TypeID) is empty in the first moment, but once re-opened, it populates with the expected information.

The code:

Note The Javascript is located in the Index page that contains the link to the modal window

This modal window is used when a New Machine is Created, or Edited. For that reason, in the first section of the Javascript, I check in which situation I am and check if the Machine property: MchName, has a value. In case it doesn't have a value, I assign the value of the variable items to the property TypeID that should be shown when the Modal opens.

@section scripts{
<script src="~/js/machine-index.js" asp-append-version="true"></script>


<script type="text/javascript">
    $(document).ready(function () {
        $('#FamilyID').change(function () {
            var url = '@Url.Content("~/")' + "Machines/GetModel";
            var ddlsource = "#FamilyID";
            $.getJSON(url, { FamilyID: $(ddlsource).val() }, function (data) {
                var items = '';
                $("#TypeID").empty();
                $.each(data, function (i, model) {
                    items += "<option value='" + model.value + "'>" + model.text + "</option>";
                });
                $('#TypeID').html(items);
            });
        });
        $('#modal-action-machine').on('shown.bs.modal', function () {
            var test = "#MchName";
            if ($(test).val()) {

            } else {
                var items = "<option value='0'>-- Seleccione Modelo --</option>";
                $('#TypeID').html(items);
            }
        });
    });
</script>
<script type="text/javascript">
    $(function () {
        $('.datepicker').datepicker({
            "autoclose": true,
            format: 'dd/mm/yyyy'
        }).datepicker("setDate", new Date());
    });
</script>
<script src="~/lib/bootstrap-datepicker/js/bootstrap-datepicker.js"></script>
}

Get Method:

    [HttpGet]
    public IActionResult CreateEdit(int? id)
    {
        //Lista de Familias
        List<MachineFamily> FamilyList = new List<MachineFamily>();
        FamilyList = (from family in _context.MachineFamilies
                      select family).ToList();
        FamilyList.Insert(0, new MachineFamily { FamilyID = 0, FamilyDescription = "-- Seleccione Familia --" });
        ViewBag.ListofFamily = FamilyList;

        ViewBag.TypeID = string.Empty;
        return PartialView("~/Views/Shared/Machines/_Create.cshtml");
    }

JsonResult:

    public JsonResult GetModel(int FamilyID)
    {
        List<MachineType> ListaModelos = new List<MachineType>();
        ListaModelos = (from model in _context.MachineTypes
                        where model.FamilyID == FamilyID
                        select model).ToList();
        ListaModelos.Insert(0, new MachineType { TypeID = 0, TypeDescription = "-- Seleccione Modelo --" });
        return Json(new SelectList(ListaModelos, "TypeID", "TypeDescription"));
    }

View: Modal

@model Application.Models.ApplicationviewModels.MachineIndexData
@using Application.Models

<form asp-action="CreateEdit" role="form">
    @await Html.PartialAsync("_ModalHeader", new ModalHeader
{ Heading = String.Format("Actualización de Modelo") })

    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    <div class="modal-body form-horizontal">
        <input type="hidden" asp-for="Id" />
        <div class="form-group">
            <label asp-for="FamilyID" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <select asp-for="FamilyID" class="form-control"
                        asp-items="@(new SelectList(ViewBag.ListofFamily,"FamilyID","FamilyDescription"))"></select>
            </div>
        </div>
        <div class="form-group">
            <label asp-for="TypeID" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <select asp-for="TypeID" class="form-control"
                        asp-items="@(new SelectList(ViewBag.TypeID,"TypeID","TypeDescription"))"></select>
            </div>
        </div>
        <div class="form-group">
            <label asp-for="BrandID" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <select asp-for="BrandID" class="form-control" asp-items="ViewBag.BrandID">
                    <option value="">-- Seleccione Marca --</option>
                </select>
                <span asp-validation-for="BrandID" class="text-danger"></span>
            </div>
        </div>
        <div class="form-group">
            <label asp-for="SupplierID" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <select asp-for="SupplierID" class="form-control" asp-items="ViewBag.SupplierID">
                    <option value="">-- Seleccione Proveedor --</option>
                </select>
                <span asp-validation-for="SupplierID" class="text-danger"></span>
            </div>
        </div>
        <div class="form-group">
            <label asp-for="StoreID" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <select asp-for="StoreID" class="form-control" asp-items="ViewBag.StoreID">
                    <option value="">-- Seleccione Tienda --</option>
                </select>
                <span asp-validation-for="StoreID" class="text-danger"></span>
            </div>
        </div>
        <div class="form-group">
            <label asp-for="MchName" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <input asp-for="MchName" class="form-control" />
                <span asp-validation-for="MchName" class="text-danger"></span>
            </div>
        </div>
        <div class="form-group">
            <label asp-for="NumDevices" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <input id="NumDevices" asp-for="NumDevices" class="form-control" readonly />
                <span asp-validation-for="NumDevices"  class="text-danger"></span>
                <input id="getNum" type="range" min="" max="10" step="1" onchange="fetch()" class="form-control" />
            </div>
        </div>
        <div class="form-group">
            <label asp-for="FechaCompra" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <input data-format="0:dd/MM/yyyy" type="datetime" asp-for="FechaCompra" class="form-control datepicker" />
                <span asp-validation-for="FechaCompra" class="text-danger"></span>
            </div>
        </div>
        <div class="form-group">
            <label asp-for="CostoMaq" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <input asp-for="CostoMaq" class="form-control" />
                <span asp-validation-for="CostoMaq" class="text-danger"></span>
            </div>
        </div>
        <div class="form-group">
            <label asp-for="MachineStatus" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <select name="MachineStatus" asp-for="MachineStatus" class="form-control" disabled>
                    <option value="0">Operativo</option>
                    <option value="1" selected="selected">Nuevo Item</option>
                    <option value="2">Reparación</option>
                </select>
                <input type="hidden" name="MachineStatus" value="1" />
                <span asp-validation-for="MachineStatus" class="text-danger"></span>
            </div>
        </div>

        @await Html.PartialAsync("_ModalFooter", new ModalFooter { })
    </div>
</form>

Final notes: I believe that to fix this I should change the Javascript. Can someone please explain to me why this happens and how to fix it?

Update: Attempting to assign a new id to the ´MchName´ field and send it to the Script

View:

    <div class="form-group">
        <label asp-for="MchName" class="col-md-2 control-label"></label>
        <div class="col-md-10">
            <input id="MchName2" asp-for="MchName" class="form-control" />
            <span asp-validation-for="MchName" class="text-danger"></span>
        </div>
    </div>

Script:

        $('#modal-action-machine').on('shown.bs.modal', function () {
            var test = document.getElementById("MchName2").value;
            if (test) {

            } else {
                var items = "<option value='0'>-- Seleccione Modelo --</option>";
                $('#TypeID').html(items);
            }
        });

No luck tho.

Update: Second attempt

View:

    <div class="form-group">
        <label asp-for="MchName" class="col-md-2 control-label"></label>
        <div class="col-md-10" id="MchName2">
            <input asp-for="MchName" class="form-control" />
            <span asp-validation-for="MchName" class="text-danger"></span>
        </div>
    </div>

Script:

        $('#modal-action-machine').on('shown.bs.modal', function () {
            var test = "#MchName2 #MchName";
            if ($(test).val()) {

            } else {
                var items = "<option value='0'>-- Seleccione Modelo --</option>";
                $('#TypeID').html(items);
            }
        });

Upvotes: 2

Views: 95

Answers (2)

I have found an answer that works for this specific case.

The first thing that was wrong was evaluate a variable that is not defined inside an ifstatement.

$('#modal-action-machine').on('shown.bs.modal', function () {
    var test = "#MchName";
    if ($(test).val()) {

In this code I was assigning the value of #MchName to testbut in a first moment, #MchName does not get defined until the modal opens for a first time, and for that, not executing the rest of the code.

Second: A turn around was to use click event of the Create button to identify if I'm in a case of a New Machine or just an update.

For this I will declare a global variable and assign it the value of zero. If the Create button is clicked, assign this variable the value of 1, and if this is true, assign the default value that was intended to the #TypeID variable.

After the modal closes, re-asign the global variable to zero. This, for the case that another button (Update) is hitted to call the modal.

This is the code:

var global = this;
var wasclicked = 0;

$(document).ready(function () {

    document.getElementById("modalbutton").onclick = function () {
        global.wasclicked = 1;
    };

    $('#modal-action-machine').on('hidden.bs.modal', function () {
        global.wasclicked = 0;
    });

    $('#modal-action-machine').on('shown.bs.modal', function () {
        if (global.wasclicked == 1) {
            var items = "<option value='0'>-- Seleccione Modelo --</option>";
            $('#TypeID').html(items);
        }

    });

With this, the project works as intended.

Thanks for the help!

Upvotes: 0

Mihai Alexandru-Ionut
Mihai Alexandru-Ionut

Reputation: 48337

You should wrap both shown.bs.modal event handlers in one single document.ready function.

Every time when shown.bs.modal event is fired, it will bind a change event handler to your select element. You should bind it only once.

script type="text/javascript">
$(document).ready(function () {
    $('#FamilyID').change(function () {
        var url = '@Url.Content("~/")' + "Machines/GetModel";
        var ddlsource = "#FamilyID";
        $.getJSON(url, { FamilyID: $(ddlsource).val() }, function (data) {
            var items = '';
            $("#TypeID").empty();
            $.each(data, function (i, model) {
                items += "<option value='" + model.value + "'>" + model.text + "</option>";
            });
            $('#TypeID').html(items);
        });
    });
    $('#modal-action-machine').on('shown.bs.modal', function () {
        var test = "#MchName";
        if ($(test).val()) {

        } else {
            var items = "<option value='0'>Select</option>";
            $('#TypeID').html(items);
        }
    });
});

Upvotes: 2

Related Questions