Вопрос по primefaces, jsf-2 – Как сделать предотвращение двойного щелчка в JSF 2
У нас есть несколько поисковых страниц, которые работают с большим количеством данных и требуют времени для завершения. Когда пользователь нажимает кнопку поиска, мы не хотим, чтобы он отправлял результаты поиска во второй раз.
Есть ли лучшая практика для выполнения "двойного щелчка"? обнаружение / профилактика в JSF?
Компонент PrimeFaces выглядит так, как будто он может делать то, что мы хотим, так как он будет отключать пользовательский интерфейс на период времени между нажатием кнопки поиска и завершением поиска, но есть ли более общая стратегия, которую мы можем использовать (возможно, это не зависит от PrimeFaces)? В идеале, любое нажатие кнопки будет либо отключено, либо проигнорировано до завершения поиска. Нам не обязательно отключать весь пользовательский интерфейс (как позволяет blockUI).
ельно попробовал каждую из них). Моя форма всегда отправлялась дважды, когда пользователь дважды нажимал кнопку входа в систему. Я работаю с 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. Надеюсь, это кому-нибудь поможет.
хорошо работает с элементом, имеющим тип ввода 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>
имея ту же проблему. Решение не сработало для меня - после краткого взгляда на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');
}
};
используемое с шаблонами 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>
слушатели. Когда пользователь нажимает на кнопку - отключить его. Когда действие выполнено - включите.
<p:commandButton id="saveBtn" onclick="$('#saveBtn').attr('disabled',true);" oncomplete="$('#saveBtn').attr('disabled',false);" actionListener="#{myBean.save}" />
вы можете использовать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
ограничение на столбец (ы) интереса.