What is the best way to disable a button so a double click doesn't occur with knockout.js. I have some users doing some quick clicking causing multiple ajax requests. I assume knockout.js can handle this in several ways and wanted to see some of the alternatives out there.
问题:
回答1:
Use a semaphore (spinning lock). Basically, you count how many clicks an element has registered and if it is more than 1 you return false and don't allow the following clicks. A timeout function could be used to clear the lock so that they could click again after say, 5 seconds. You could modify the example from http://knockoutjs.com/documentation/click-binding.html
As seen here:
<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>
By changing the logic inside the nested function to
if( this.numberOfClicks() > 1 ){
//TODO: Handle multiple clicks or simply return false
// and perhaps implement a timeout which clears the lockout
}
回答2:
I ran into a similar problem with a form wizard submitting data via Ajax on button click. We have 4 buttons selectively visible for each step. We created a boolean observable ButtonLock
and returned from the submission function if it was true. Then we also data-bound the disable
of each button to the ButtonLock
observable
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);
}
Button:
<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);
}"/>
If you just need to prevent multiple clicks, I prefer the boolean. But the counter method lets you detect double clicks and handle them separately, if you want that feature.
回答3:
In case anyone is still looking for a way to do this. I found that You can use a boolean.
self.disableSubmitButton= ko.observable(false);
self.SubmitPayment = function () {
self.disableSubmitButton(true);
//your other actions here
}
Then in your view
data-bind="click:SubmitPayment, disable:disableSubmitButton"
回答4:
I did this with a custom binding:
<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);
})
}
}