Ajax call to refresh partial view on detail page not working after edit action from modal.
I have a partial in a Detail
view. I use a modal with the edit action to update the child relationship of the record in the Detail
view. When I hit Save
on the edit modal, the record updates, and I want the partial that holds the child relationship data to refresh, instead of the whole page refreshing.
So far, I've been able to get the edit modal to work with ajax. But my script for refreshing the partial isn't working. I put a breakpoint in the controller action called by the ajax script but when clicking the Save
button on the modal edit form the breakpoint never fires. I don't know why the controller action isn't being called by the ajax script.
The Detail
view has a bootstrap tabbed view. The tab I am working on is the Relationships
tab. When I use the Edit
modal to update a relationship, I want the Relationship
tab to refresh, not the whole page.
The Edit
modal is a view component based on the Relationship
model, and the Detail
view is based on the Contact
model. This part works. I put the line return NoContent();
at the end of the Relationship
controller POST;Edit
action. I used the click event of the Save
button to handle closing the Edit
modal and refreshing the partial in the Detail
view.
Flow.
In the Detail view Relationships tab, I have the partial view that shows the relationships.
<div class="tab-pane fade" id="nav-relationship" role="tabpanel" aria-labelledby="nav-relationship-tab">
<partial name="_RelationshipsTab"/>
</div>
The Partial view that I want to refresh after editing
@if (@Model.RelationshipsAsParent.Count > 0)
{
<table class="table table-bordered">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Type</th>
<th></th>
</tr>
</thead>
<tbody>
@for (int j = 0; j < Model.RelationshipsAsParent.Count; j++)
{
<tr>
<td>@Model.RelationshipsAsParent[j].Child.FullName</td>
<td>@Model.RelationshipsAsParent[j].RelationshipType.Type</td>
<td>
<a onclick="RelationshipsEdit(@Model.RelationshipsAsParent[j].Id)" class="btn btn-sm btn-primary">
Edit
</a> |
<a asp-controller="Relationships" asp-action="Delete" asp-route-id="@Model.RelationshipsAsParent[j].Id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
}
else
{
<h3>No Relationships</h3>
}
When I click on the Edit button for a relationship, it opens a modal based on a view componant
@model SelfReference.Models.Relationship
@{
ViewData["Title"] = "Edit";
}
<div class="row">
<div class="col-md-4">
<form asp-controller="Relationships" asp-action="Edit">
@* data-ajax="true" data-ajax-mode="replace" data-ajax-update="#nav-relationship" *@
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id" />
<div class="form-group">
<label asp-for="ParentId" class="control-label"></label>
<select asp-for="ParentId" class="form-control" asp-items="ViewBag.ParentId"></select>
<span asp-validation-for="ParentId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ChildId" class="control-label"></label>
<select asp-for="ChildId" class="form-control" asp-items="ViewBag.ChildId"></select>
<span asp-validation-for="ChildId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="RelationshipTypeId" class="control-label"></label>
<select asp-for="RelationshipTypeId" class="form-control" asp-items="ViewBag.RelationshipTypeId"></select>
<span asp-validation-for="RelationshipTypeId" class="text-danger"></span>
</div>
<hr />
<div class="form-group">
@* <input type="submit" value="Save" class="btn btn-primary" /> *@
<button onclick="refreshRelationships(this)" type="submit" value="Save" class="btn btn-primary">Save</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</form>
</div>
</div>
@*
<div>
<a asp-action="Index">Back to List</a>
</div> *@
@section Scripts {
@{
await Html.RenderPartialAsync("_ValidationScriptsPartial");
}
}
I edit the relationship and click the Save button. All the above works. The record is updated in the database. If I manually refresh the page, the updated changes show in the Detail view.
Here is the ajax script that updates the record.
function RelationshipsEdit(id) {
req = $.ajax({
url: "/Contacts/RelationshipsEdit/" + id,
method: "POST",
data: { id: id },
contentType: "application/json; charset=utf-8",
dataType: "text",
success: function (data) {
$("#RelationshipsComponent").html("");
$("#RelationshipsComponent").html(data);
}
});
openEdit();
};
I basically pass the id of the record clicked on to the controller action so it can do its thing.
public ActionResult RelationshipsEdit(int id)
{
return ViewComponent("RelationshipsEdit", new { id });
}
So all this works. I just need the _RelationshipsTab partial in the Detail view to update without refreshing the whole page.
Here is what doesn't work.
I click on the Save button in the Edit modal.
<button onclick="refreshRelationships(this)" type="submit" value="Save" class="btn btn-primary">Save</button>
I call this ajax script.
function refreshRelationships(evt) {
evt.preventDefault();
closeEdit();
req = $.ajax({
url: "/Contacts/RefreshRelationshipsTab/",
method: "GET",
data: {},
contentType: "application/json; charset=utf-8",
dataType: "html",
success: function (response) {
$("#nav-relationship").html(response);
}
});
};
Which calls this controller action
public async Task<ActionResult> RefreshRelationshipsTab()
{
return PartialView("_RelationshipsTab");
}
But nothing happens. I put a breakpoint in the RefreshRelationshipsTab action but it never fires. I assume the action is never being called.
Any help would be greatly appreciated.