我的视图文件中有此脚本,其目的是填充同一视图的一部分,但仅填充其中的一小部分,这是具有Bootstrap面板类的HTML div:
<script type="text/javascript">
function GetVehicles() {
$.get('@Context.Request.Scheme://@hostname/@controller/GetVehicles', {id: @Model.Id}, function (response) {
$("#tabOutVehicles").html(response);
});
}
function GetMedInfo() {
$.get('@Context.Request.Scheme://@hostname/@controller/GetMedInfo', {id: @Model.Id}, function (response) {
$("#tabOutMedInfo").html(response);
});
}
</script>
我的完整视图,它将显示上面脚本生成的输出:
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<script src="~/js/site.js"></script>
<div class="panel panel-primary">
<div class="panel-heading">
<a href="#collapseVehicles" class="btn student-dash-btn" onclick="GetVehicles()" data-toggle="collapse">Vehicles</a>
</div>
<div id="collapseVehicles" class="panel-collapse collapse">
<div id="tabOutVehicles">
</div>
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<a href="#collapseMedInfo" class="btn student-dash-btn" onclick="GetMedInfo()" data-toggle="collapse"><strong style="color:white">Medical Info</strong></a>
</div>
<div id="collapseMedInfo" class="panel-collapse collapse">
<div id="tabOutMedInfo">
</div>
</div>
</div>
<script type="text/javascript">
function GetVehicles() {
$.get('@Context.Request.Scheme://@hostname/@controller/GetVehicles', {id: @Model.Id}, function (response) {
$("#tabOutVehicles").html(response);
});
}
function GetMedInfo() {
$.get('@Context.Request.Scheme://@hostname/@controller/GetMedInfo', {id: @Model.Id}, function (response) {
$("#tabOutMedInfo").html(response);
});
}
</script>
通过单击Bootstrap面板div内的超链接,jQuery方法将命中我的控制器动作,返回响应,然后将响应放入适用的div(#tabOutMedInfo / #tabOutVehicles)。这两个动作都返回部分视图。这是我的局部视图,除了模型属性不同之外,两者都相同:
@model MyViewModel
<div class="panel-body">
<a data-url="@Url.Action("EditMedInfo", "Controller", new { id = Model.Id })" data-toggle="ajax-modal" data-target="#EditMedInfo" class="btn btn-default">Edit</a>
<div class="form-horizontal">
<div class="">
<div class="form-group">
<div class="col-md-5 col-sm-5 col-xs-5"><label asp-for="Variable" class="control-label"></label></div>
<div class="col-md-7 col-sm-7 col-xs-7">
@Html.DisplayFor(item => item.Variable)
</div>
</div>
</div>
</div>
</div>
单击上面的超链接时,应该执行JavaScript代码,该代码将加载用于编辑的模态,这不会发生,而是不会打开该模态。 JavaScript代码位于我的site.js文件中,该文件正在我的主视图中导入。
我尝试过的事情:
我将脚本导入标签移动到两个局部视图中,然后将其从视图中删除,然后使JavaScript代码运行并显示我的模态,但是此解决方案仅能使用一段时间。
新问题:
然后开始出现一个新问题,如果加载了第一个部分视图,而您要在不关闭网页的情况下加载第二个部分视图,则会导致site.js两次被加载到视图中,一次被第一个部分视图加载,第二部分是第二次观看。将site.js加载两次后,它将以某种方式导致我的发布操作被点击两次,从而导致一次发布操作两次插入了数据。
然后我决定将site.js移至_Layout.cshtml(理想情况下应如此),然后再次尝试,这种方式导致部分视图以正常方式呈现,但是再次,模态不显示何时单击部分视图中的超链接。
我的理论:
据我了解,当jQuery get方法加载部分视图时,即使它是由_Layout.cshtml加载的,它也阻止了部分视图看到site.js。
我最好不要更改的内容
我不想摆脱小的get操作,我这样做是为了使用户尽可能多地停留在一页上,并且分别调用get操作可以减少他们的数据使用量。
我可以正确加载site.js吗?为什么我的局部视图看不到site.js?
修改:
这是我的 _Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
<environment names="Development">
@*Other scripts omitted *@
<script src="~/js/site.js" asp-append-version="true" defer></script>
</environment>
<environment names="Staging,Production">
@*Other scripts omitted *@
<script src="~/js/site.js" asp-append-version="true" defer></script>
</environment>
</head>
<body>
<div id="modal-placeholder"></div>
@RenderBody()
@RenderSection("scripts", required: false)
</body>
</html>
这是 site.js 中的JavaScript代码:
$(function () {
var placeholderElement = $('#modal-placeholder');
var redirectUrl = "";
$('a[data-toggle="ajax-modal"]').click(function (event) {
var url = $(this).data('url');
redirectUrl = window.location.href;
$.get(url).done(function (data) {
placeholderElement.html(data);
placeholderElement.find('.modal').modal('show');
});
});
placeholderElement.on('click', '[data-save="modal"]', function (event) {
event.preventDefault();
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
var dataToSend = form.serialize();
$.post(actionUrl, dataToSend).done(function (data) {
var newBody = $('.modal-body', data);
placeholderElement.find('.modal-body').replaceWith(newBody);
var isValid = newBody.find('[name="IsValid"]').val() == 'True';
if (isValid) {
placeholderElement.find('.modal').modal('hide');
window.location.assign(redirectUrl);
}
}
});
});
});
JavaScript的编写方式与上面类似,用于处理模态上的服务器端验证,请参见此处的精彩文章:https://softdevpractice.com/blog/asp-net-core-mvc-ajax-modals/
答案 0 :(得分:3)
从ajax调用返回后,当将面板的HTML“粘贴”到页面中时,它将中断所有现有的事件处理程序。因此,您需要重新绑定处理程序锚元素。我会将事件处理程序包装在一个函数中,并在初始页面加载时以及在ajax成功处理程序中(在粘贴HTML之后)调用该函数。假设您使用的是jQuery,它看起来像这样:
function bindAjaxModalButtons() {
$('[data-toggle="ajax-modal"]').click(function() {
// ... your event handler code here
});
}
$(function() {
bindAjaxModalButtons(); // attaches event handlers on initial page load
});
然后像这样更改ajax函数:
function GetMedInfo() {
$.get('@Context.Request.Scheme://@hostname/@controller/GetMedInfo', {id: @Model.Id}, function (response) {
$("#tabOutMedInfo").html(response);
bindAjaxModalButtons(); // <-- this will attach the event handler to the new buttons
});
}
编辑:现在我可以看到您的JS文件,这是它的外观:
$(function () {
var placeholderElement = $('#modal-placeholder');
var redirectUrl = "";
bindAjaxModalButtons();
placeholderElement.on('click', '[data-save="modal"]', function (event) {
event.preventDefault();
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
var dataToSend = form.serialize();
$.post(actionUrl, dataToSend).done(function (data) {
var newBody = $('.modal-body', data);
placeholderElement.find('.modal-body').replaceWith(newBody);
var isValid = newBody.find('[name="IsValid"]').val() == 'True';
if (isValid) {
placeholderElement.find('.modal').modal('hide');
window.location.assign(redirectUrl);
}
}
});
});
});
function bindAjaxModalButtons() {
var btns = $('a[data-toggle="ajax-modal"]');
btns.unbind(); // <-- so that existing buttons don't get double-bound
btns.click(function (event) {
var url = $(this).data('url');
redirectUrl = window.location.href;
var placeholderElement = $('#modal-placeholder');
$.get(url).done(function (data) {
placeholderElement.html(data);
placeholderElement.find('.modal').modal('show');
});
});
}