web-dev-qa-db-ja.com

JSF 2でダブルクリック防止を行う方法

多くのデータに対して実行され、完了するまでに時間がかかる検索ページがいくつかあります。ユーザーが検索ボタンをクリックしたときに、2回目に検索結果を送信することを許可しません。

JSFで「ダブルクリック」の検出/防止を行うためのベストプラクティスはありますか?

PrimeFacesコンポーネントは、検索ボタンがクリックされてから検索が完了するまでの期間、UIを無効にするため、私たちが望むことを実行できるようですが、使用できるより一般的な戦略があります(おそらく、 PrimeFacesに依存していますか?理想的には、ボタンがクリックされると、検索が完了するまで無効または無視されます。私たちは必ずしもUI全体を無効にする必要はありません(blockUIを使用すると、そうすることができます)。

27
BestPractices

Ajaxリクエストのみを使用している場合は、JSF JavaScript APIの_jsf.ajax.addOnEvent_ハンドラーを使用できます。以下の例は、_type="submit"_のすべてのボタンに適用されます。

_function handleDisableButton(data) {
    if (data.source.type != "submit") {
        return;
    }

    switch (data.status) {
        case "begin":
            data.source.disabled = true;
            break;
        case "complete":
            data.source.disabled = false;
            break;
    }    
}

jsf.ajax.addOnEvent(handleDisableButton);
_

または、特定のボタンのみでこれが必要な場合は、_<f:ajax>_のonevent属性を使用します。

_<h:commandButton ...>
    <f:ajax ... onevent="handleDisableButton" />
</h:commandButton>
_

これを同期リクエストにも適用する必要がある場合は、onclickの間にボタンを無効にすると、ボタンの_name=value_ペアがリクエストパラメータとして送信されず、したがって、JSFはアクションを識別して呼び出すことができません。したがって、無効にする必要がありますPOSTリクエストがブラウザから送信されました。DOMイベントハンドラはありませんこのためには、setTimeout()ハックを使用する必要があります。これにより、クリックしてから50ミリ秒後にボタンが無効になります。

_<h:commandButton ... onclick="setTimeout('document.getElementById(\'' + this.id + '\').disabled=true;', 50);" />
_

これはかなり壊れやすいだけです。遅いクライアントでは短すぎるかもしれません。タイムアウトを増やすか、別のソリューションに進む必要があります。

とはいえ、これはWebページで送信する場合にのみ二重送信を防止することに注意してください。これは、URLConnection、Apache HttpClient、JsoupなどのプログラムによるHTTPクライアントによる二重送信を防止しません。データモデルに一意性を適用する場合は、二重送信を防止するのではなく、二重挿入を防止する必要があります。これは、SQLで対象の列にUNIQUE制約を設定することで簡単に実現できます。

以下も参照してください。

35
BalusC

私にとってはこのように動作します:

<h:commandLink ... onclick="jQuery(this).addClass('ui-state-disabled')">
1
Alessandro

私は同じ問題を抱えてこの質問に出くわしました。 primefaces.js を簡単に調べた後、このソリューションは私にとってはうまくいきませんでした。私は彼らがjsf.ajaxをもう使用していないと思います。

だから私は自分で何かをしなければならなかった、そしてここで私の解決策があります---でそれを使うこともできない人々のための BalusCによる答え

// we override the default send function of
// primeFaces here, so we can disable a button after a click
// and enable it again after     

var primeFacesOriginalSendFunction = PrimeFaces.ajax.AjaxUtils.send;

PrimeFaces.ajax.AjaxUtils.send = function(cfg){    
  var callSource = '';

  // if not string, the caller is a process - in this case we do not interfere

  if(typeof(cfg.source) == 'string') {

    callSource = jQuery('#' + cfg.source);
    callSource.attr('disabled', 'disabled');

  }



  // in each case call original send
  primeFacesOriginalSendFunction(cfg);

  // if we disabled the button - enable it again
  if(callSource != '') {

    callSource.attr('disabled', 'enabled');

  }

};
1
user2862701

'onclick'および 'oncomplete'リスナーを使用できます。ユーザーがボタンをクリックしたとき-無効にします。アクションが完了したとき-有効にします。

<p:commandButton id="saveBtn" onclick="$('#saveBtn').attr('disabled',true);" oncomplete="$('#saveBtn').attr('disabled',false);" actionListener="#{myBean.save}" />
1

上記の代替案はどれもうまくいきませんでした(私は実際にそれらのそれぞれを試しました)。ユーザーがログインボタンをダブルクリックすると、フォームが常に2回送信されました。 Glassfish 3.1.2でJSF(Mojarra 2.1.6)を使用しています。

AJAX以外のログインページであると考えてください。

だからここに私がそれを解決した方法があります:

  1. ページヘッダーまたはフォーム外の任意の場所で送信を制御するグローバルJavaScript変数を定義します。
var submitting = false;
  1. 送信時にtrueに設定h:form onsubmitイベントが発生します:
<h:form onsubmit="submitting = true">
  1. H:commandLinkのクリックイベントで変数の値を確認します。
<h:commandLink ... onclick="if(submitting){return false}">

これは単なるもう1つの単純な代替手段であり、Chrome [Version 47.0.2526.106(64-bit)]]、Mozilla Firefox(37.0.2)、およびInternet Explorer 11でテストされています。 。

1
Jaumzera

ファセットテンプレートで使用される非常に有用なソリューションjsf-primefacesは、他のページの消費者に広がります

<f:view>
    <Script language="javascript">
        function checkKeyCode(evt)
        {
            var evt = (evt) ? evt : ((event) ? event : null);
            var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
            if(event.keyCode==116)
            {
                evt.keyCode=0;
                return false
            }
        }
        document.onkeydown=checkKeyCode;

        function handleDisableButton(data) {
            if (data.source.type != "submit") {
                return;
            }

            switch (data.status) {
                case "begin":
                    data.source.disabled = true;
                    break;
                case "complete":
                    data.source.disabled = false;
                    break;
            }    
        }
        jsf.ajax.addOnEvent(handleDisableButton);
    </Script>

</f:view>

<h:head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link href="./resources/css/default.css" rel="stylesheet" type="text/css" />
    <link href="./resources/css/cssLayout.css" rel="stylesheet" type="text/css" />
    <title>infoColegios - Bienvenido al Sistema de Administracion</title>
</h:head>

<h:body onload="#{login.validaDatos(e)}">
    <p:layout fullPage="true">

        <p:layoutUnit position="north" size="120" resizable="false" closable="false" collapsible="false">                   
            <p:graphicImage value="./resources/images/descarga.jpg" title="imagen"/> 
            <h:outputText value="InfoColegios - Bienvenido al Sistema de Administracion" style="font-size: large; color: #045491; font-weight: bold"></h:outputText>                    
        </p:layoutUnit>

        <p:layoutUnit position="west" size="175" header="Nuestra Institución" collapsible="true" effect="drop" effectSpeed="">
            <p:menu> 
                <p:submenu>
                    <p:menuitem value="Quienes Somos" url="http://www.primefaces.org/showcase-labs/ui/home.jsf" />

                </p:submenu>
            </p:menu>
        </p:layoutUnit>

        <p:layoutUnit position="center">
            <ui:insert name="content">Content</ui:insert>
        </p:layoutUnit>

    </p:layout>
</h:body>
0
user1947165

非表示と表示で簡単な作業を行いましたが、入力タイプがサブミットJqueryの要素でうまく機能しました

$(":submit").click(function (event) {
        // add exception to class skipDisable 
        if (!$(this).hasClass("skipDisable")) {
            $(this).hide();
                        $(this).after("<input type='submit' value='"+$(this).val()+"' disabled='disabled'/>");
        }
    });</ code>
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
        <form>
        <input type="submit" value="hello">
        </form>
0
Anupam