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?
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.
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="btnAdd-@item.Id"
:
<button class="btn btn-primary" data-toggle="modal" data-target="@("#AddEmp-"+item.Id)"
data-url="@Url.Action($"AddEmployee/{item.Id}")" id="btnAdd-@item.Id">Add Employees</button>
<script>
$('#AddEmp-@Html.Raw(item.Id)').on('click', '#btnSave', function (e) {
document.getElementById("btnAdd-@item.Id").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>
$('#AddEmp-@Html.Raw(item.Id)').on('click', '#btnSave', function (e) {
$('#AddEmp-@Html.Raw(item.Id)').closest('.btn-group-sm').find("#btnAdd").prop('disabled', true);
})
</script>
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.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="btnAdd-@item.DepId">Add Employees</button>
@await Html.PartialAsync("_AddEmployeePartialView", item)
<script>
$('#AddEmp-@Html.Raw(item.DepId)').on('click', '#btnSave', function (e) {
e.preventDefault(); //prevent form submit...
document.getElementById("btnAdd-@item.DepId").disabled = true;
console.log($('#AddEmp-@item.DepId').find('form').serialize());
$.ajax({
method:"POST",
url:"/Home/AddEmployee", //replace your url....
data: $('#AddEmp-@item.DepId').find('form').serialize(),
success:function(data){
if(data){
$('#AddEmp-@item.DepId').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);
}