2012-04-24 4 views
14

Jaki jest najlepszy sposób na wyłączenie przycisku, aby podwójne kliknięcie nie występowało w pliku knockout.js. Niektórzy użytkownicy robią szybkie kliknięcia, powodując wiele zapytań ajaxowych. Zakładam, że knockout.js poradzi sobie z tym na kilka sposobów i chciał zobaczyć niektóre alternatywy.Zapobieganie dwukrotnemu kliknięciu przycisku z knockout.js

Odpowiedz

13

Użyj semafora (spinning lock). Zasadniczo liczymy liczbę kliknięć zarejestrowanych przez element, a jeśli jest więcej niż 1, zwracamy wartość false i nie zezwalamy na następujące kliknięcia. Funkcji limitu czasu można użyć, aby usunąć blokadę, aby mogły ponownie kliknąć po powiedzeniu, 5 sekund. Można zmodyfikować przykład z http://knockoutjs.com/documentation/click-binding.html

Jak widać tutaj:

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

Poprzez zmianę logiki wewnątrz funkcji zagnieżdżonych do

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

Świetna odpowiedź! Może to również zostać przekształcone w niestandardowe wiązanie kliknięć. – madcapnmckay

+0

Doskonała odpowiedź. Poszedłem dalej i zawijałem wszystkie moje połączenia w ten sposób bez problemu, i resetowałem kliknięcia po każdym wywołaniu ajax, ogólnie rzecz biorąc. Zastanawiam się, jak może wyglądać niestandardowe powiązanie. –

10

wpadłem na podobny problem z czarodziejem forma przekazywania danych przez Ajax po kliknięciu przycisku. Mamy 4 przyciski selektywnie widoczne dla każdego kroku. Stworzyliśmy boolean obserwowalny ButtonLock i zwróciliśmy go z funkcji składania, jeśli to prawda. Wtedy też danych związała disable każdego przycisku do ButtonLock obserwowalne

ViewModel:

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); 
    } 

Przycisk:

<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); 
     }"/> 

Jeśli wystarczy, aby zapobiec wielu klika, wolę logiczną . Jednak metoda licznika pozwala wykrywać podwójne kliknięcia i obsługiwać je osobno, jeśli chcesz tę funkcję.

+4

Podoba mi się ta odpowiedź więcej. Daje to użytkownikowi wizualny wskaźnik tego, co się dzieje, a co z liczeniem. Użytkownik może kilkakrotnie kliknąć przycisk i bez wskazania, co się dzieje, aby mogli pomyśleć, że coś się zepsuło. – MorganTiley

+0

Zgadzam się z @MorganTiley, jest to lepsze rozwiązanie –

4

Jeśli ktoś nadal szuka sposobu, aby to zrobić. Zauważyłem, że możesz użyć wartości boolowskiej.

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

Następnie w widoku

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

Zrobiłem to ze zwyczajem Oprawa:

<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); 
     }) 
    } 
}