Search code examples
javascriptasp.net-core-mvcpartial-views

Disable button in parent view from partial view


I have parent view "index.cshtml" and partial view"_AddEmployeePartialView.cshtml". I'm currently trying to figure out how to disable a button "Add Employees" once the button "Save" in the partial view is clicked and partial view is closed of course. I'm not good at javascript so I appreciate any help I may receive. this is the code i used:

index.chtml:

@model IEnumerable<Department>

@{
    ViewData["Title"] = "Department";
}
<table class="table table-bordered table-hover">
                <thead>
                    <tr>
                        <th>
                            @Html.DisplayNameFor(model => model.DepId)
                        </th>
                        <th>
                            @Html.DisplayNameFor(model => model.DepName)
                        </th>
                        
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                    @foreach (var item in Model)
                    {
                        <tr>
                            <td>
                                @Html.DisplayFor(modelItem => item.DepId)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.DepName)
                            </td>
                            
                            <td>
                                <div class="btn-group-sm">
                                    
                                        <button class="btn btn-primary" data-toggle="modal" data-target="@("#AddEmp-"+item.DepId)" data-url="@Url.Action($"AddEmployee/{item.DepId}")" id="btnAdd" >Add Employees</button>
                                        @await Html.PartialAsync("_AddEmployeePartialView", item)
                                    
                                <script>
                                    $('#AddEmp-' + @Html.Raw(item.DepId)).on('click', '#btnSave', function () {
                                        document.getElementById("btnAdd").disabled = true;
                                </script>
                                </div>
                            </td>
                        </tr>
                    }
                </tbody>
            </table>

_AddEmployeePartialView.cshtml:

    @model management.Models.Employee

@{
    ViewData["Title"] = "_AddEmployeePartialView";

}

<div class="modal fade" role="dialog" tabindex="-1" id="@("AddEmp-"+Model.DepId)"  aria-labelledby="addEmpLabel" aria-hidden="true" >
    <div class="modal-dialog " role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h3 class="modal-title">Employees</h3>
            </div>
            <div class="modal-body">
               
                <form asp-action="AddEmployee" method="post">
                    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                    <input asp-for="DepId" type="hidden" />
                    
                            <table class="table table-bordered" >
                                <thead>
                                    <tr>
                                        <th>Employee name</th>
                                        <th>Profession</th>
                                        <th>Phone</th>
                                        
                                    </tr>
                                </thead>
                                <tbody>


                                    @for (int i = 0; i < Model.Employees.Count; i++)
                                    {
                                        <tr>

                                            <td>
                                                @Html.EditorFor(x => x.Employees[i].EmpName, new { htmlAttributes = new { @class = "form-control" } })
                                            </td>

                                            <td>
                                                @Html.EditorFor(x => x.Employees[i].Profession, new { htmlAttributes = new { @class = "form-control" } })
                                            </td>
                                            <td>
                                                @Html.EditorFor(x => x.Employees[i].Phone, new { htmlAttributes = new { @class = "form-control" } })
                                            </td>
                                           
                                        </tr>
                                    }
    
                                </tbody>
                            </table>
                        
                    
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-dismiss="modal" onclick="javascript:window.location.reload()">Cancel</button>
                        <button type="submit" class="btn btn-primary" id="btnSave">Save</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>

This code is not working, the button in the index view isn't disabled. how to solve this?


Solution

    1. Your btnSave button is a submit button, after it hits the backend AddEmployee action, the page will be refreshed. Then the js function will not work any more. You need use ajax to call the backend code to avoid refreshing.

    2. All of the partial views will be rendered when the page load at first time. So there are multiple buttons with same id btnAdd. Your js code could always find the first button.

    • A quick way is to make these buttons with uniqure id like id="[email protected]":

      <button class="btn btn-primary" data-toggle="modal" data-target="@("#AddEmp-"+item.Id)" 
             data-url="@Url.Action($"AddEmployee/{item.Id}")" id="[email protected]">Add Employees</button>
      
      <script>
          $('#[email protected](item.Id)').on('click', '#btnSave', function (e) {
              document.getElementById("[email protected]").disabled = true;            
          })
      </script>
      
    • Or if you do not want to change the button id, you can find it like below:

      <button class="btn btn-primary" data-toggle="modal" data-target="@("#AddEmp-"+item.Id)" 
                data-url="@Url.Action($"AddEmployee/{item.Id}")" id="btnAdd">Add Employees</button>
      
      <script>
          $('#[email protected](item.Id)').on('click', '#btnSave', function (e) {
              $('#[email protected](item.Id)').closest('.btn-group-sm').find("#btnAdd").prop('disabled', true);
          })
      </script>
      
    1. Your main view passes item in the @await Html.PartialAsync("_AddEmployeePartialView", item), the item is type of Department. But your partial view requires @model management.Models.Employee. If they do not match, it would make error.

    The whole working demo

    Model:

    public class Department
    {
        public int DepId { get; set; }
        public string? DepName { get; set; }
        public List<Employee>? Employees { get; set; }
    }
    public class Employee
    {
        public string? Phone { get; set; }
        public string? EmpName { get; set; }
        public string? Profession { get; set; }
    }
    

    Main View(Index.cshtml):

    @model IEnumerable<Department>
    
    @{
        ViewData["Title"] = "Department";
    }
    <table class="table table-bordered table-hover">
        <thead>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.DepId)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.DepName)
                </th>
    
                <th></th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model)
            {
                <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.DepId)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.DepName)
                    </td>
                    <td>
                        <div class="btn-group-sm">
    
                        <button class="btn btn-primary" data-toggle="modal" data-target="@("#AddEmp-"+item.DepId)" data-url="@Url.Action($"AddEmployee/{item.DepId}")" id="[email protected]">Add Employees</button>
                        @await Html.PartialAsync("_AddEmployeePartialView", item)
    
                        <script>
                            $('#[email protected](item.DepId)').on('click', '#btnSave', function (e) {
                                e.preventDefault();   //prevent form submit...
                                document.getElementById("[email protected]").disabled = true;
                                console.log($('#[email protected]').find('form').serialize());
                                $.ajax({
                                    method:"POST",
                                    url:"/Home/AddEmployee",   //replace your url....
                                    data: $('#[email protected]').find('form').serialize(),
                                    success:function(data){
                                        if(data){
                                             $('#[email protected]').modal('hide');
                                        }
                                    }
                                })
                                    
                            })
                        </script>
                        </div>
                    </td>
                </tr>
            }
        </tbody>
    </table>   
    

    Partial View(_AddEmployeePartialView.cshtml):

    @model Department
    @{
        ViewData["Title"] = "_AddEmployeePartialView";
    }
    <div class="modal fade" role="dialog" tabindex="-1" id="@("AddEmp-"+Model.DepId)" aria-labelledby="addEmpLabel" aria-hidden="true">
        <div class="modal-dialog " role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h3 class="modal-title">Employees</h3>
                </div>
                <div class="modal-body">
    
                    <form asp-action="AddEmployee" method="post">
                        <input asp-for="DepId" type="hidden" />
    
                        <table class="table table-bordered">
                            <thead>
                                <tr>
                                    <th>Employee name</th>
                                    <th>Profession</th>
                                    <th>Phone</th>
    
                                </tr>
                            </thead>
                            <tbody>
                                @for (int i = 0; i < Model.Employees.Count; i++)
                                {
                                    <tr>
    
                                        <td>
                                            @Html.EditorFor(x => x.Employees[i].EmpName, new { htmlAttributes = new { @class = "form-control" } })
                                        </td>
    
                                        <td>
                                            @Html.EditorFor(x => x.Employees[i].Profession, new { htmlAttributes = new { @class = "form-control" } })
                                        </td>
                                        <td>
                                            @Html.EditorFor(x => x.Employees[i].Phone, new { htmlAttributes = new { @class = "form-control" } })
                                        </td>
    
                                    </tr>
                                }
    
                            </tbody>
                        </table>
    
                        <div class="modal-footer">
                            <button type="button" class="btn btn-secondary" data-dismiss="modal" onclick="javascript:window.location.reload()">Cancel</button>
                            <button type="submit" class="btn btn-primary" id="btnSave">Save</button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
    

    Backend action:

    [HttpPost]
    public IActionResult AddEmployee(Department model)
    {
        if (ModelState.IsValid)
        {
            try
            {
                //do your database add operation...
                return Json(true);
            }
            catch (Exception)
            {
    
                return Json(false);
            }
        }
        return Json(false);
    }