Extend a specific jQuery method in ASP.NET MVC jquery.unobtrusive-ajax.js

Question:

I'm using @Ajax.BeginForm() extensions methods to save the data via AJAX. To avoid performing more than one click on the submit button, which could cause a double insert in my database, I decided to include a small code snippet inside the jquery.unobtrusive-ajax.js file, which disables the submit button.

I included the code snippet right after the method calls that display a loader, respectively loading.show(duration); and loading.hide(duration); .

Here is the complete method where I added my code:

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 = parseInt(element.getAttribute("data-ajax-loading-duration"), 10) || 0;

    $.extend(options, {
        context: element,
        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);
                $("form[data-ajax=true] :submit").attr('disabled', 'disabled').addClass('disabled'); //adicionado para evitar novo clique após submit
            }
            return result;
        },
        complete: function () {
            loading.hide(duration);
            $("form[data-ajax=true] :submit").removeAttr('disabled').removeClass('disabled'); //adicionado para evitar clique após submit
            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"])
    });

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

The excerpts I include:

loading.show(duration);
$("form[data-ajax=true] :submit").attr('disabled', 'disabled').addClass('disabled');

e:

loading.hide(duration);
$("form[data-ajax=true] :submit").removeAttr('disabled').removeClass('disabled');

That adds and removes a disabled="disabled" attribute and a class also disabled to the submit button right after the loading element is displayed and hidden.

This works perfectly, the only problem is that since I'm editing a code that microsoft maintains, if a new version of the file is published, I will lose my code. So my question is whether it is possible to create a similar effect, with some extension of this file, that could be written in a separate script in a separate file.

Answer:

Analyzing the code of jquery.unobstrusive-ajax.js , I could verify that there are some points that can be extended, putting attributes in the form generated by Ajax.BeginForm :

  • data-ajax-begin : this attribute can point to a global function, present in window , or it can contain the javascript code directly, which will be executed before making the ajax request.

  • data-ajax-complete : this attribute can point to a global function, present in window , or it can contain the javascript code directly, which will be executed when the ajax completes.

That said, you can create functions to be included in a javascript file like this:

function ajaxBegin()
{
    //adicionado para evitar novo clique após submit
    $("form[data-ajax=true] :submit").attr('disabled', 'disabled').addClass('disabled');
}

function ajaxComplete()
{
    //adicionado para evitar novo clique após submit
    $("form[data-ajax=true] :submit").attr('disabled', 'disabled').addClass('disabled');
}

And in that same javascript file, already use a method to change the form generated by the Ajax.BeginForm method, which conveniently have the data-ajax="true" attribute:

$(function () {
    $("form[data-ajax=true]")
        .attr("data-ajax-begin", "ajaxBegin")
        .attr("data-ajax-complete", "ajaxComplete");
}

Once that's done, you'll have to include this javascript file in every page that wants this behavior:

  • you could put this script at the top of Microsoft's jquery.unobtrusive-ajax.js file (putting code at the top is easier than editing something in the middle of the file)

  • you can put it in the _Layout.cshtml file if you have a layout file

Then it's up to you, the best way to include it on every page.

Scroll to Top