Вопрос по primefaces, jsf-2 – Как сделать предотвращение двойного щелчка в JSF 2

25

У нас есть несколько поисковых страниц, которые работают с большим количеством данных и требуют времени для завершения. Когда пользователь нажимает кнопку поиска, мы не хотим, чтобы он отправлял результаты поиска во второй раз.

Есть ли лучшая практика для выполнения "двойного щелчка"? обнаружение / профилактика в JSF?

Компонент PrimeFaces выглядит так, как будто он может делать то, что мы хотим, так как он будет отключать пользовательский интерфейс на период времени между нажатием кнопки поиска и завершением поиска, но есть ли более общая стратегия, которую мы можем использовать (возможно, это не зависит от PrimeFaces)? В идеале, любое нажатие кнопки будет либо отключено, либо проигнорировано до завершения поиска. Нам не обязательно отключать весь пользовательский интерфейс (как позволяет blockUI).

Ваш Ответ

6   ответов
0

ельно попробовал каждую из них). Моя форма всегда отправлялась дважды, когда пользователь дважды нажимал кнопку входа в систему. Я работаю с JSF (Mojarra 2.1.6) над Glassfish 3.1.2.

Учтите, что это была страница входа без AJAX.

Вот как я это решил:

define a global JavaScript var to control submition in the page header or anywhere outside your form:
var submitting = false;
set it to true when submit h:form onsubmit event is fired:
<h:form onsubmit="submitting = true">
Check the var's value on h:commandLink's click event:
<h:commandLink ... onclick="if(submitting){return false}">

Это просто еще одна простая альтернатива, и она была протестирована в Chrome [Версия 47.0.2526.106 (64-разрядная версия)], Mozilla Firefox (37.0.2) и Internet Explorer 11. Надеюсь, это кому-нибудь поможет.

Большое спасибо, @BestPractices, но я не понял твою точку зрения. Я перепробовал все другие альтернативы, и мое единственное, что работает в моем случае. Я не говорю, что они не правы, я просто разделяю мою точку зрения, пытаясь внести свой вклад в этот вопрос.
Поверьте, у вас возникла проблема с кнопкой «Назад». Отправьте форму, а затем нажмите кнопку «Назад», чтобы вернуться на эту страницу. Значение отправляющей переменной, скорее всего, «истинно». BestPractices
0

хорошо работает с элементом, имеющим тип ввода submit 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'/>");
        }
    });
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
        <form>
        <input type="submit" value="hello">
        </form>
1

имея ту же проблему. Решение не сработало для меня - после краткого взгляда наprimefaces.js Я думаю, что они больше не используют jsf.ajax там.

поэтому мне пришлось самому что-то придумать, и вот мое решение, для людей, которые также не могут использовать вышеуказанное:

// 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');

  }

};
Бит jquery должен быть callSource = $ (PrimeFaces .escapeClientId (cfg.source));
Важно, чтобы код не запускался дважды (в противном случае вы быстро столкнетесь с проблемами производительности или даже сбоями).
Начиная с PrimeFaces 5, API изменился. PrimeFaces.ajax.AjaxUtils.send, вероятно, стал PrimeFaces.ajax.Request.send.
0

используемое с шаблонами Facelets, распространяется на другие страницы потребителей

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

1

слушатели. Когда пользователь нажимает на кнопку - отключить его. Когда действие выполнено - включите.

<p:commandButton id="saveBtn" onclick="$('#saveBtn').attr('disabled',true);" oncomplete="$('#saveBtn').attr('disabled',false);" actionListener="#{myBean.save}" />
Это не сработало. Я все еще был в состоянии нажать кнопку несколько раз, пока действие обрабатывалось.
33

вы можете использоватьjsf.ajax.addOnEvent обработчик JSF JavaScript API для этого. Приведенный ниже пример будет применен ко всем кнопкам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);

В качестве альтернативы, если вам это нужно только на определенных кнопках, используйтеonevent атрибут<f:ajax>.

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

Если вам также необходимо применить это к синхронным запросам, то вы должны принять во внимание, что при отключении кнопки во времяonclickзатем кнопкиname=value пара не будет отправлена как параметр запроса, и, следовательно, JSF не сможет определить действие и вызвать его. Таким образом, вы должны только отключить егоafter запрос POST был отправлен браузером. Для этого нет обработчика событий DOM, вам нужно использоватьsetTimeout() Взлом, который отключает кнопку ~ 50 мс после нажатия.

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

Это только довольно хрупко. Это может быть слишком мало для медленных клиентов. Вам необходимо увеличить время ожидания или перейти к другому решению.

Тем не менее, имейте в виду, что это только предотвращает двойную передачу при отправке через веб-страницу. Это не предотвращает двойную передачу программными HTTP-клиентами, такими какURLConnection, Apache HttpClient, Jsoup и т. Д. Если вы хотите обеспечить уникальность в модели данных, то вам не следует предотвращать двойную передачу, а предотвращать двойную вставку. Это может быть легко достигнуто в SQL путемUNIQUE ограничение на столбец (ы) интереса.

See also: Pure Java/JSF implementation for double submit prevention How to handle multiple submits before response is rendered?

Похожие вопросы