如何在MVC3 Ajax.ActionLink OnBegin,OnComplete Events中使用$(this)
我的控制器创建了这样的链接列表
@foreach (var item in Model.MenuItems) { - @Ajax.ActionLink(item.Caption, item.ActionName, item.ControllerName, new AjaxOptions { UpdateTargetId = "pageBody", OnBegin = "BeginUpdatePage", OnComplete = "EndUpdatePage", OnFailure = "FailUpdatePage" })
}
我有一些像这样的JavaScript
function BeginUpdatePage() { $("#MainMenu li").removeClass('selected'); $(this).parent().addClass('selected'); $("#pageBody").fadeTo('slow', 0.5); } function EndUpdatePage() { $("#pageBody").fadeTo('slow', 1); } function FailUpdatePage() { alert('There has been an error loading this page please try again.'); }
在BeginUpdatePage函数第1行和第3行执行正常,但第2行“$(this).parent()。addClass(’selected’);” 不会做任何事……(我已经在我的CSS中宣布了这个课程)。
我查看了Jquery文档( Jquery.ajax() )它说“this”是被点击的元素。 我还检查了默认情况下在我的项目中的“jquery.unobtrusive-ajax.js”。 执行我的函数时,此文件也会传递“this”。
"result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(this,arguments);"
我在这里做错了什么……我见过其他使用过这种技术的例子 ,但我一整天都失败了!
如何在Begin,complete函数中找到被单击的元素。
更新2014年1月20日 :不显眼的ajax脚本的官方3.1版本包含此更改,并与MVC 5.1版本(1月17日)同时发布。 去检查看看:-)
原始回复
我偶然发现了这一点 ,以达到你想要的结果。 很简单。
绕过jquery.unobtrusive-ajax.js文件大约第100行,添加这一行代码。
options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" }); options.context = element; // <--- Add this line method = options.type.toUpperCase(); if (!isMethodProxySafe(method)) { options.type = "POST"; options.data.push({ name: "X-HTTP-Method-Override", value: method }); }
就是这样,你现在应该能够使用this
来引用源元素。
您可以尝试这样传递:
OnBegin = "function() { BeginUpdatePage(this); }"
然后:
function BeginUpdatePage(element) { $("#MainMenu li").removeClass('selected'); $(element).parent().addClass('selected'); $("#pageBody").fadeTo('slow', 0.5); }
或者只是使用jQuery而不使用任何Ajax.*
东西:
@foreach (var item in Model.MenuItems) { - @Html.ActionLink( item.Caption, item.ActionName, item.ControllerName, null, new { @class = "someLink" } )
}
然后:
$(function() { $('.someLink').click(function() { var link = $(this); $.ajax({ url: this.href, beforeSend: function() { $("#MainMenu li").removeClass('selected'); $(link).parent().addClass('selected'); $("#pageBody").fadeTo('slow', 0.5); }, complete: function() { $("#pageBody").fadeTo('slow', 1); }, success: function(result) { $('#pageBody').html(result); }, error: function() { alert('There has been an error loading this page please try again.'); } }); return false; }); });
感谢大家提出的所有建议,Darin,虽然您的解决方案完美无缺,但我想尝试使用内置的Ajax实用程序。
在查看Jquery.Ajax()Docs并检查“jquery.unobtrusive-ajax.js”之后,我找到了一个解决方法。这更像是一个Hack而不是正确使用,我不确定是谁放了“jquery.unobtrusive-ajax。 js“汇总在一起,但如果有人知道如何通过电子邮件发送给他们,可能会向他们发送一个指向此页面的链接:-)
这是“jquery.unobtrusive-ajax.js”中有趣的部分,在这个函数“function asyncRequest(element,options)”中
$.extend(options, { type: element.getAttribute("data-ajax-method") || undefined, url: element.getAttribute("data-ajax-url") || undefined, beforeSend: function (xhr) { var result; asyncOnBeforeSend(xhr, method); result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(this, arguments); if (result !== false) { loading.show(duration); } return result; }, complete: function () { loading.hide(duration); getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(this, arguments); }, success: function (data, status, xhr) { asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html"); getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(this, arguments); }, error: getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]) });
当这段代码在发送,完成,错误之前的每一步调用apply方法时,它传入两个perams,“this”和“arguments”……
Wich工作创建,但在上下文中“this”是XHR(XMLHttpRequest)而不是被点击的元素…通过检查函数头,您可以看到它将XHR对象作为第一个参数传递。 那么为什么我们还需要它作为调用上下文呢?
我的解决方案……更改“jquery.unobtrusive-ajax.js”和“jquery.unobtrusive-ajax-min.js”文件……
而不是在apply方法上传递“this”(XHR),让我们发送实际的元素!
所以整个function现在看起来像这样:
function asyncRequest(element, options) { var confirm, loading, method, duration; confirm = element.getAttribute("data-ajax-confirm"); if (confirm && !window.confirm(confirm)) { return; } loading = $(element.getAttribute("data-ajax-loading")); duration = element.getAttribute("data-ajax-loading-duration") || 0; $.extend(options, { type: element.getAttribute("data-ajax-method") || undefined, url: element.getAttribute("data-ajax-url") || undefined, beforeSend: function (xhr) { var result; asyncOnBeforeSend(xhr, method); result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(element, arguments); if (result !== false) { loading.show(duration); } return result; }, complete: function () { loading.hide(duration); getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(element, arguments); }, success: function (data, status, xhr) { asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html"); getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(element, arguments); }, error: getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]) }); options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" }); method = options.type.toUpperCase(); if (!isMethodProxySafe(method)) { options.type = "POST"; options.data.push({ name: "X-HTTP-Method-Override", value: method }); } $.ajax(options); }
现在,当您创建处理这些事件的函数时,可以使用“this”来获取实际元素。
例:
function BeginUpdatePage(xhr) { $("#MainMenu li").removeClass('selected'); $(this).parent().addClass('selected'); $("#pageBody").fadeTo('slow', 0.5); } function EndUpdatePage(xhr,status) { $("#pageBody").fadeTo('slow', 1); } function FailUpdatePage(data,status,xhr) { alert('There has been an error loading this page please try again.'); }
现在对于某些人来说,我更容易使用Darin的解决方案,只需编写自己的Jquery来处理点击事件,嘿,你可能有更好的控制权,
但我相信内置的东西也应该有效。 不必乱用它。 因此,我希望有人可以certificate我是错的,并且实际上有更好的方法可以做到这一点,或者将这个脚本放在一起的人可以改变它。
除非他们有充分的理由这样做吗? 解释欢迎:-)
再次感谢所有对此问题提出好建议的人,我希望这对未来的人们有所帮助。
检查event.srcElement怎么样?
我有另一种解决方案,它使用AJAX URL来选择被点击的原始链接。 只有一个具有确切URL的ActionLink,此解决方案才能正常工作:
function BeginUpdatePage() { // Get the URL that will be posted to var targetUrl = this.url; var sourceLink = null; // loop through all action links applicable $('#MainMenu a').each(function () { var href = $(this).attr('href'); // the targetUrl contains the entire URL - including http:// // so we need to do an indexOf to see if the href is contained // within the target URL if (targetUrl.indexOf(href) > -1) { sourceLink = $(this); return false; } }); // we've now got the link that was clicked - do with it as you wish... sourceLink.parent().addClass('selected'); }