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.
Detail
Save
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.
Relationships
Edit
Relationship
Contact
return NoContent();
POST;Edit
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.