10

私のコントローラーは、このようなリンクのリストを作成します

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

私はここで何が間違っているのですか...私はこのテクニックを使用した他の例を見ましたが、私は一日中失敗しています!

Begin内のクリックされた要素に到達するにはどうすればよいですか?

4

5 に答える 5

10

2014 年 1 月 20 日更新: 目立たない ajax スクリプトの公式 3.1 バージョンにはこの変更が含まれており、MVC 5.1 リリース (1 月 17 日) と同時に公開されました。ぜひチェックしてみてください:-)

元の応答

あなたが探している結果を達成するために、私はしばらく前にこれに出くわしました。とても簡単です。

jquery.unobtrusive-ajax.js ファイルの約 100 行目に、この 1 行のコードを追加します。

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これで、ソース要素を参照するために使用できるはずです。

于 2013-01-30T18:38:55.070 に答える
4

次のように渡すことができます。

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;
    });
});
于 2011-07-08T20:37:17.567 に答える
3

Darin さん、ご提案ありがとうございます。あなたのソリューションは完璧に機能しますが、組み込みの Ajax ユーティリティを試してみたかったのです。

Jquery.Ajax() Docsを見て、「jquery.unobtrusive-ajax.js」を調べた後、回避策を見つけました。これは適切な使用というよりもハックです。誰が「jquery.unobtrusive-ajax. js" ファイルを一緒に送信しますが、メールの送信方法を知っている人は、このページへのリンクを送ってください :-)

これは、この関数「function asyncRequest(element, options)」の「jquery.unobtrusive-ajax.js」の興味深い部分です。

$.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"])
    });

このコードがbeforeSend、Complete、error の各ステップでapplyメソッドを呼び出すと、「this」と「arguments」の 2 つのパラメーターが渡されます...

作成は機能しますが、コンテキストでは「これ」はクリックされた要素ではなくXHR(XMLHttpRequest)です...また、関数ヘッダーを調べると、XHRオブジェクトが最初のperamとして渡されることがわかります。では、なぜそれを呼び出しコンテキストにする必要があるのでしょうか?

私の解決策...「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.');
}

一部の人々にとっては、クリックイベントを処理するために独自の Jquery を作成するだけで、Darin のソリューションを使用する方が簡単です。おそらく、すべてをより適切に制御できます。

しかし、組み込みのものも機能するはずだと私は信じています。それをいじる必要はありません。ですから、誰かが私が間違っていることを証明し、実際にはこれを行うより良い方法があるか、またはこのスクリプトをまとめた人がそれを変更できることを願っています.

彼らがこのようにする正当な理由がない限り?説明歓迎:-)

この質問に対して良い提案をしてくれたすべての人に感謝します。これが将来人々に役立つことを願っています。

于 2011-07-09T11:54:00.643 に答える
0

AJAX URL を使用して、クリックされた元のリンクを選択する別のソリューションがあります。このソリューションは、正確な URL を持つ ActionLink が 1 つしかない場合にのみ適切に機能します。

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');
}
于 2011-12-09T12:22:04.133 に答える
0

event.srcElement を確認してみてはどうでしょうか。

于 2011-09-28T00:03:01.440 に答える