Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use $(this) inside MVC3 Ajax.ActionLink OnBegin,OnComplete Events

My Controller creates a list of links like this

<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>

I have some javascript like this

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.');
}

in the BeginUpdatePage function line 1 and 3 execute fine, but line 2 "$(this).parent().addClass('selected');" does not visiably do anything... (I have declared that class in my css).

I have looked at Jquery docs (Jquery.ajax()) it says that "this" is the element that was clicked. I have also checked in "jquery.unobtrusive-ajax.js" that was in my project by default. This file also passes "this" when executing my function.

"result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(this,arguments);"

What am I doing wrong here... I have seen other examples that have used this technique but I have been failing all day!

How can I get to the element that was clicked, inside my Begin, complete functions.

like image 342
MichaelLake Avatar asked Jul 08 '11 20:07

MichaelLake


2 Answers

UPDATE Jan 20, 2014: The official 3.1 version of the unobtrusive ajax script contains this change, and was published at the same time as the MVC 5.1 release (Jan 17th). Go check check it out :-)

Original response

I came across this a while back to achieve the result you are looking for. VERY simple to do.

Arround approximately line # 100 of the jquery.unobtrusive-ajax.js file, add this one line of code.

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 });
}

That's it, you should be able to use this to reference the source element now.

like image 100
Nick Albrecht Avatar answered Oct 14 '22 19:10

Nick Albrecht


You could try passing it like this:

OnBegin = "function() { BeginUpdatePage(this); }"

and then:

function BeginUpdatePage(element) {
    $("#MainMenu li").removeClass('selected');
    $(element).parent().addClass('selected');
    $("#pageBody").fadeTo('slow', 0.5);
}

or simply use jQuery without any Ajax.* stuff:

<ul id="MainMenu">
    @foreach (var item in Model.MenuItems)
    {
        <li>
            @Html.ActionLink(
                item.Caption,
                item.ActionName,
                item.ControllerName,
                null,
                new { @class = "someLink" }
            )
        </li>
    }
</ul>

and then:

$(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;
    });
});
like image 38
Darin Dimitrov Avatar answered Oct 14 '22 19:10

Darin Dimitrov