我的控制器会创建一个像这样的链接列表
<ul id="MainMenu">
@foreach (var item in Model.MenuItems)
{
<li>@Ajax.ActionLink(item.Caption,
item.ActionName,
item.ControllerName,
new AjaxOptions
{
UpdateTargetId = "pageBody",
OnBegin = "BeginUpdatePage",
OnComplete = "EndUpdatePage",
OnFailure = "FailUpdatePage"
})
</li>
}
</ul>
我有一些像这样的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);"
我在这里做错了什么......我见过使用过这种技术的other examples但是我整天都失败了!
如何在Begin,complete函数中找到被单击的元素。
答案 0 :(得分:10)
更新2014年1月20日:不显眼的ajax脚本的官方3.1版本包含此更改,并与MVC 5.1版本(1月17日)同时发布。去检查一下: - )
原始回复
我偶然遇到了this,以达到你想要的结果。非常简单。
在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
来引用源元素。
答案 1 :(得分:3)
您可以尝试这样传递:
OnBegin = "function() { BeginUpdatePage(this); }"
然后:
function BeginUpdatePage(element) {
$("#MainMenu li").removeClass('selected');
$(element).parent().addClass('selected');
$("#pageBody").fadeTo('slow', 0.5);
}
或简单地使用jQuery而不使用任何Ajax.*
内容:
<ul id="MainMenu">
@foreach (var item in Model.MenuItems)
{
<li>
@Html.ActionLink(
item.Caption,
item.ActionName,
item.ControllerName,
null,
new { @class = "someLink" }
)
</li>
}
</ul>
然后:
$(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;
});
});
答案 2 :(得分:3)
感谢大家提出的所有建议,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 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来处理点击事件,嘿,你可能有更好的控制权,
但我相信内置的东西也应该有效。不必乱用它。 所以我希望有人可以证明我是错的,实际上有更好的方法可以做到这一点,或者将这个脚本放在一起的人可以改变它。
除非他们有充分的理由这样做吗?欢迎解释: - )
再次感谢所有对此问题提出好建议的人 我希望这有助于将来的人们。
答案 3 :(得分:0)
检查event.srcElement怎么样?
答案 4 :(得分:0)
我有另一种解决方案,它使用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');
}