2012-04-24 26 views
14

¿Cuál es la mejor manera de desactivar un botón para que no se produzca un doble clic con knockout.js? Tengo algunos usuarios haciendo clic rápido causando múltiples solicitudes ajax. Supongo que knockout.js puede manejar esto de varias maneras y quería ver algunas de las alternativas disponibles.Evite hacer doble clic en un botón con knockout.js

Respuesta

13

Utilice un semáforo (bloqueo giratorio). Básicamente, usted cuenta cuántos clics ha registrado un elemento y si es más de 1, devuelve falso y no permite los siguientes clics. Se podría usar una función de tiempo de espera para borrar el bloqueo para que puedan hacer clic de nuevo después de decir, 5 segundos. Se podría modificar el ejemplo de http://knockoutjs.com/documentation/click-binding.html

Como se ve aquí:

<div> 
You've clicked <span data-bind="text: numberOfClicks"></span> times 
<button data-bind="click: incrementClickCounter">Click me</button> 
</div> 

<script type="text/javascript"> 
var viewModel = { 
    numberOfClicks : ko.observable(0), 
    incrementClickCounter : function() { 
     var previousCount = this.numberOfClicks(); 
     this.numberOfClicks(previousCount + 1); 
    } 
}; 
</script> 

Al cambiar la lógica dentro de la función anidada para

if(this.numberOfClicks() > 1){ 
//TODO: Handle multiple clicks or simply return false 
// and perhaps implement a timeout which clears the lockout 
} 
+0

Gran respuesta! Esto también podría refactorizarse en un enlace de clic personalizado. – madcapnmckay

+0

Respuesta perfecta. Seguí adelante y envolví todas mis llamadas sin problemas, y reinicié los clics después de cada llamada ajax, genéricamente por supuesto. Me pregunto cómo se vería un enlace personalizado. –

10

me encontré con un problema similar con un formulario de datos asistente presentación a través de Ajax al hacer clic en el botón. Tenemos 4 botones selectivamente visibles para cada paso. Creamos un boolean observable ButtonLock y lo devolvimos de la función de envío si era verdadero. Entonces también enlazado a datos del disable de cada botón a la ButtonLock observables

modelo de vista:

var viewModel = function(...) { 
    self.ButtonLock = ko.observable(false); 

    self.AdvanceStep = function (action) { 
     self.ButtonLock(true); 
     // Do stuff 
     // Ajax call 
    } 

    self.AjaxCallback = function(data) { 
     // Handle response, update UI 
     self.ButtonLock(false); 
    } 

Botón:

<input type="button" id="FormContinue" name="FormContinue" class="ActionButton ContinueButton" 
    data-bind=" 
     if: CurrentStep().actions.continueAction, 
     disable: ButtonLock, 
     value: CurrentStep().actions.continueAction.buttonText, 
     click: function() { 
      AdvanceStep(CurrentStep().actions.continueAction); 
     }"/> 

Si sólo tiene que evitar que varios clics, prefiero el booleano . Pero el método de contador le permite detectar clics dobles y manejarlos por separado, si desea esa función.

+4

Me gusta esta respuesta más. Le da al usuario un indicador visual de lo que está sucediendo frente al enfoque de conteo. El usuario puede hacer clic repetidamente en el botón y sin indicador de lo que está sucediendo para que pueda pensar que algo se rompió. – MorganTiley

+0

Estoy de acuerdo con @MorganTiley, esta es una solución mejor –

4

En caso de que alguien todavía esté buscando una forma de hacerlo. Encontré que puedes usar un booleano.

self.disableSubmitButton= ko.observable(false); 
    self.SubmitPayment = function() { 
     self.disableSubmitButton(true); 
     //your other actions here 
     } 

A continuación, en su opinión

data-bind="click:SubmitPayment, disable:disableSubmitButton" 
0

Hice esto con la unión de un encargo:

<button data-bind="throttleClick: function() { console.log(new Date()); }> 
    I wont double click quicker than 800ms 
</button> 

ko.bindingHandlers.throttleClick = { 
    init: function(element, valueAccessor) { 
     var preventClick = false; 
     var handler = ko.unwrap(valueAccessor()); 

     $(element).click(function() { 
      if(preventClick) 
       return; 

      preventClick = true; 
      handler.call(); 
      setTimeout(function() { preventClick = false; }, 800); 
     }) 
    } 
} 
Cuestiones relacionadas