Comment faire double-cliquez sur prévention dans JSF 2

nous avons quelques pages de recherche qui fonctionnent contre beaucoup de données et prennent un certain temps à compléter. Lorsqu'un utilisateur clique sur le bouton de recherche, nous aimerions ne pas leur permettre de soumettre le résultat de la recherche un second temps.

Existe-t-il une pratique exemplaire pour effectuer la détection/prévention "en double-clic" dans le JSF?

le composant PrimeFaces semble pouvoir faire ce que nous voulons car il va désactiver L'UI pour une période de temps entre le moment où le bouton de recherche est cliqué et lorsque la recherche est terminée, mais y a-t-il une stratégie plus générique que nous pouvons utiliser (peut-être quelque chose qui ne dépend pas de PrimeFaces)? Idéalement, tout clic du bouton sera désactivé ou ignoré jusqu'à ce que la recherche soit terminée. Nous n'avons pas nécessairement besoin de désactiver L'UI entière (comme blockUI vous permet de le faire).

24
demandé sur BestPractices 2012-05-25 18:41:21

6 réponses

si vous utilisez uniquement des requêtes ajax, vous pouvez utiliser jsf.ajax.addOnEvent handler de L'API JavaScript JSF pour cela. L'exemple ci-dessous s'applique à tous les boutons de 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);

alternativement, si vous en avez besoin sur des boutons spécifiques seulement, utilisez l'attribut onevent de <f:ajax> .

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

si vous devez également appliquer cela sur les requêtes synchrones, alors vous devez tenir compte que lorsque vous désactivez un lors de onclick , la paire de boutons name=value ne sera pas envoyée comme paramètre de requête et JSF ne pourra donc pas identifier l'action et l'invoquer. Vous ne devez donc le désactiver qu'après la demande de poste a été envoyée par le navigateur. Il n'y a pas de gestionnaire D'événements DOM pour cela, vous devez utiliser le hack setTimeout() qui désactive le bouton ~50ms après avoir cliqué.

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

C'est plutôt fragile. C'est peut-être trop court sur les clients lents. Vous devez augmenter le temps mort ou vous diriger vers une autre solution.

cela dit, Gardez à l'esprit que cela n'empêche que double soumet lors de la soumission par une page web. Cela n'empêche pas les doubles soumissions par des clients HTTP programmatiques comme URLConnection , Apache HttpClient, Jsoup, etc. Si vous voulez imposer l'unicité dans le modèle de données, alors vous ne devriez pas empêcher les doubles soumissions, mais empêcher les doubles inserts. Cela peut être facilement réalisé en SQL en mettant un UNIQUE contrainte sur la colonne(s) d'intérêt.

voir aussi:

32
répondu BalusC 2017-05-23 11:46:19

je suis venu sur cette question, ayant le même problème. La solution n'a pas fonctionné pour moi - après un bref coup d'oeil sur les primefaces .js je suppose qu'ils n'utilisent pas jsf.ajax est encore là.

donc j'ai dû trouver quelque chose moi-même et voici ma solution, pour les gens qui ne peuvent pas utiliser celui ci-dessus:

// 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
répondu user2862701 2013-10-09 12:17:03

vous pouvez utiliser les écouteurs 'onclick' et 'oncomplete'. Lorsque l'utilisateur clic sur le bouton désactiver. Lorsque l'action est terminée-activer.

<p:commandButton id="saveBtn" onclick="$('#saveBtn').attr('disabled',true);" oncomplete="$('#saveBtn').attr('disabled',false);" actionListener="#{myBean.save}" />
1
répondu Vladimir Tsukanov 2013-10-30 17:29:54

très utile solution jsf primefaces, utilisé avec facelets modèle se propage à d'autres pages consommateurs

<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
répondu user1947165 2013-01-04 00:25:56

aucune des alternatives ci-dessus n'a fonctionné pour moi (j'ai vraiment essayé chacune d'entre elles). Mon formulaire a toujours été envoyé deux fois lorsque l'utilisateur double-cliqué le bouton de connexion. Je travaille avec JSF (Mojarra 2.1.6) sur Glassfish 3.1.2.

considère que c'était une page de connexion non-AJAX.

alors voici comment je l'ai résolu:

  1. définissez une var globale JavaScript pour contrôler la submition dans l'en-tête de page ou n'importe où en dehors de votre formulaire:
var submitting = false;
  1. est réglé à true lorsque soumettre h:form onsubmit événement est déclenché:
<h:form onsubmit="submitting = true">
  1. Vérifiez la valeur du var sur H: événement de clic de commandLink:
<h:commandLink ... onclick="if(submitting){return false}">

c'est juste une autre alternative simple et il a été testé dans Chrome [Version 47.0.2526.106 (64-bit)], Mozilla Firefox (37.0.2) et Internet Explorer 11. J'espère que c' aide à quelqu'un.

0
répondu Jaumzera 2016-05-13 23:36:43

a fait un travail simple avec hide and show, fonctionne bien avec l'élément ayant le type d'entrée 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>
0
répondu Anupam 2016-07-21 05:39:20