You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Razor Pages:更新数据后Partial View刷新页面及事件重绑定问题

问题描述

已实现Razor Pages中通过Partial View更新数据后刷新页面的功能,但表格列表中的Update按钮仅能生效一次。由于重新加载表格内容会导致Update事件绑定失效,请问该如何重新绑定该事件?


index.cshtml页面

@page
@model RazorPagesCollection.Pages.PopUp.IndexModel
@using Northwind_EF.Models
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous" />
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
    <script type="text/javascript">
        $(function () {
            $("#CustomerGrid .details").click(function () {
                var customerId = $(this).closest("tr").find("td").eq(0).html();
                $.ajax({
                    type: "POST",
                    url: "Index?handler=GetDetails",
                    headers:
                    {
                        "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
                    },
                    data: { "customerId": customerId },
                    success: function (response) {
                        $("#partialModal").find(".modal-body").html(response);
                        $("#partialModal").modal('show');
                    },
                    failure: function (response) {
                        alert(response.responseText);
                    },
                    error: function (response) {
                        alert(response.responseText);
                    }
                });
            });


            $("#CustomerGrid .updatePopup").click(function () {
                var customerId = $(this).closest("tr").find("td").eq(0).html();
                $.ajax({
                    type: "POST",
                    url: "Index?handler=UpdateRecordView",
                    headers:
                    {
                        "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
                    },
                    data: { "customerId": customerId },
                    success: function (response) {
                        $("#partialModal").find(".modal-body").html(response);
                        $("#partialModal").modal('show');
                    },
                    failure: function (response) {
                        alert(response.responseText);
                    },
                    error: function (response) {
                        alert(response.responseText);
                    }
                });
            });

            $("#divCustomer .updatePost").on("click", function (e) {
                console.log("Posting Form Data....");
                var customerId = $(this).closest("tr").find("td").eq(0).html();
                var data = $("#form1").serialize();
                $.ajax({
                    type: "POST",
                    url: "Index?handler=UpdateRecord",
                    data: data,
                    headers:
                    {
                        "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
                    },
                    success: function (response) {
                        console.log(response);
                        $("#partialModal").modal('hide');
                        $("#CustomerGrid").load("index #CustomerGrid");
                    },
                    failure: function (response) {
                        alert(response.responseText);
                    },
                    error: function (response) {
                        alert(response.responseText);
                    }
                });
            });

        });


        function PostProcessFormID(id) {
            //check valid if you have client side validation...
            valid = $('#' + id).valid();
            console.log("id: " + valid);

            if (valid) {
                thisForm = document.getElementById(id);
                var data = new FormData(thisForm);
                $.ajax({
                    type: "POST",
                    url: "Index?handler=UpdateRecord",
                    data: data,
                    headers:
                    {
                        "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
                    },
                    success: function (response) {
                        console.log(response);
                        $("#partialModal").modal('hide');
                        $("#CustomerGrid").load("index #CustomerGrid");
                    },
                    failure: function (response) {
                        alert(response.responseText);
                    },
                    error: function (response) {
                        alert(response.responseText);
                    }
                });
            }
        }
    </script>

</head>
<body>

    <h4>Customers</h4>
    <hr />
    <div id="divCustomer">
        <table cellpadding="0" cellspacing="0" class="table table-striped table-condensed table-responsive" id="CustomerGrid">
            <tr>
                <th>CustomerID</th>
                <th>Company Name</th>
                <th>City</th>
                <th>Country</th>
                <th></th>
                <th></th>
            </tr>
            @foreach (Customer customer in Model.Customers)
            {
                <tr>
                    <td>@customer.CustomerID</td>
                    <td>@customer.CompanyName</td>
                    <td>@customer.City</td>
                    <td>@customer.Country</td>
                    <td><a class="details" href="javascript:;">View</a></td>
                    <td><a class="updatePopup" href="javascript:;">Update</a></td>
                </tr>
            }
        </table>
        @Html.AntiForgeryToken()
        <div id="partialModal" class="modal" tabindex="-1" role="dialog">
            <div class="modal-dialog" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title">Customer Details Form</h5>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>
                    <div class="modal-body">
                    </div>
                    
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                        <button type="button" id="btnEdit" data-toggle="modal" class="btn btn-primary updatePost">Update</button>
                    </div>
                    
                </div>
            </div>
        </div>
    </div>
</body>
</html>

Index.cshtml.cs后台代码

using EF_DBContext;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Northwind_EF.Models;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace RazorPagesCollection.Pages.PopUp
{
    public class IndexModel : PageModel
    {

        private NorthwinDbContext Context { get; }
        public IndexModel(NorthwinDbContext _context)
        {
            this.Context = _context;
        }

        public List<Customer> Customers { get; set; }

        public void OnGet()
        {
            this.Customers = (from customer in this.Context.Customers.Take(10)
                              select customer).ToList();
        }

        public PartialViewResult OnPostGetDetails(string customerId)
        {
            return new PartialViewResult
            {
                ViewName = "Details",
                ViewData = new ViewDataDictionary<Customer>(ViewData, this.Context.Customers.Find(customerId))
            };
        }

        public PartialViewResult OnPostUpdateRecordView(string customerId)
        {
            return new PartialViewResult
            {
                ViewName = "Update",
                ViewData = new ViewDataDictionary<Customer>(ViewData, this.Context.Customers.Find(customerId))
            };
        }

        public IActionResult OnPostUpdateRecord(Customer customer)
        {
            Customer updatedCustomer = (from c in this.Context.Customers
                                        where c.CustomerID == customer.CustomerID
                                        select c).FirstOrDefault();

            if (updatedCustomer != null)
            {
                updatedCustomer.CompanyName = customer.CompanyName ;
                updatedCustomer.Country = customer.Country;
                this.Context.SaveChanges();
                return Content("Updated Successfully");
            }
            else
            {
                return Content("Updated Failed");
            }
        }

    }
}

Partial View更新页面

@model Northwind_EF.Models.Customer
@{
    Layout = null;
}

<form id="form1" method="POST" onsubmit="PostProcessFormID('form1'); return false;">
    <table cellpadding="0" cellspacing="0" border="0">
        <tr>
            <th>Name</th>
            <td><input asp-for="CompanyName" class="form-control" /></td>
        </tr>

        <tr>
            <th>Address</th>
            <td><input asp-for="Address" class="form-control" /></td>
        </tr>
        <tr>
            <th>City</th>
            <td><input asp-for="City" class="form-control" /></td>
        </tr>
        <tr>
            <th>Country</th>
            <td><input asp-for="Country" class="form-control" /></td>
        </tr>
        <tr>
            <th>PostalCode</th>
            <td><input asp-for="PostalCode" class="form-control" /></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="Update" class="btn btn-primary" /></td>
            <td colspan="2"><input type="button" value="Cancel" class="btn btn-dark" /></td>
        </tr>
    </table>

    <input type="hidden" name="CustomerID" asp-for="CustomerID" value="@Model.CustomerID" />
</form>

解决方案

问题出在你直接把事件绑定到了动态生成的DOM元素上,当表格通过$("#CustomerGrid").load()重新加载后,原来的按钮元素被替换,之前绑定的事件也跟着失效了。解决办法是用事件委托,把事件绑定到一个始终存在的父元素上,让父元素监听子元素的事件。

具体修改步骤

把原来的.click()事件绑定改成用.on()绑定到父元素#CustomerGrid:

// 替换原来的 $("#CustomerGrid .details").click(...)
$("#CustomerGrid").on("click", ".details", function () {
    var customerId = $(this).closest("tr").find("td").eq(0).html();
    $.ajax({
        type: "POST",
        url: "Index?handler=GetDetails",
        headers:
        {
            "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
        },
        data: { "customerId": customerId },
        success: function (response) {
            $("#partialModal").find(".modal-body").html(response);
            $("#partialModal").modal('show');
        },
        failure: function (response) {
            alert(response.responseText);
        },
        error: function (response) {
            alert(response.responseText);
        }
    });
});

// 替换原来的 $("#CustomerGrid .updatePopup").click(...)
$("#CustomerGrid").on("click", ".updatePopup", function () {
    var customerId = $(this).closest("tr").find("td").eq(0).html();
    $.ajax({
        type: "POST",
        url: "Index?handler=UpdateRecordView",
        headers:
        {
            "RequestVerificationToken": $('input:hidden[name="__RequestVerificationToken"]').val()
        },
        data: { "customerId": customerId },
        success: function (response) {
            $("#partialModal").find(".modal-body").html(response);
            $("#partialModal").modal('show');
        },
        failure: function (response) {
            alert(response.responseText);
        },
        error: function (response) {
            alert(response.responseText);
        }
    });
});

原理说明

事件委托利用了DOM的事件冒泡机制:当子元素触发点击事件时,事件会向上冒泡到父元素。通过在父元素上监听事件,并指定目标子元素的选择器,就能确保即使子元素是动态生成的,事件依然能被正常触发。

额外优化建议

  • 可以把重复的AJAX逻辑封装成通用函数,减少代码冗余,比如提取获取CustomerID、发送POST请求的公共方法。
  • 注意PostProcessFormID函数里的表单验证,如果没引入jQuery Validation插件,$('#' + id).valid()会报错,需要确保相关脚本已正确引入。

内容的提问来源于stack exchange,提问作者Milacay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 01:44:52