bootstrap-touchspin
bootstrap-touchspin copied to clipboard
Change event firing multiple times
The change
event fires twice when pressing any of the the spinner buttons and 3 times when moving out the input field by pressing the TAB
key after modifying its value.
I'm listening to this event in order to update a record in a database. Because of this behavior, I'm hitting my database 2 to 3 times per change.
I've confirmed this is not something else in my application by disabling the TouchSpin and leaving the input as the regular HTML one. In this case the change
event happens only once.
Any way to solve this?
There is the problem. The change event triggered two times when entering to the input value from keybord which is between allowed values by step. For example, I set step = 10. Current value is 0, I entered 7 from keyboard and change event triggered with 7 value, after that plugin rounded 7 to 10 and change event triggered for second time
I cant even find a temporary solution because there is no way to figure out in change callback it was triggered by keyboard entering or from touchspin.js
I resolved this issue for my purposes by adding an additional if statement in the _checkValue function:
if (Number(val).toString() !== returnval.toString()) {
if (originalinput.val() === returnval) {
return;
}
originalinput.val(returnval);
originalinput.trigger('change');
}
Hope this helps.
Cant we merge this solution to the component library ?
I found a temporary work around,
$(this).TouchSpin({ .... , forcestepdivisibility: null, ....});
By default the forcestepdivisibility
is set to round
which converts the value to a float.
The problem arises when the val
is a string like 2.0
and the conversion Number(val).toString()
will convert it to 2
. This will result in the change
event being triggered each time the blur event is triggered, not just when the value is changed.
I suspect a better fix to the snippet of code above is:
if (parseFloat(Number(val).toString()) !== parseFloat(returnval.toString())) {
originalinput.val(returnval);
originalinput.trigger('change');
}
The inner if
statement will now only be entered if the numeric value has actually changed.
thanks a lot for even a better solution. Since it is your idea, can you maybe commit this solution to the project so we can all use it?
I created a pull request. See: https://github.com/istvan-ujjmeszaros/bootstrap-touchspin/pull/132
It is fixed in master, and a new version is published to npm (v4.4.0). Feel free to reopen if you still encounter multiple change events, but please provide the steps to reproduce. I could only reproduce what @MaxSpirihin described and fixed that by specially handling the TAB and ENTER keys on the input.
For my purposes the problem is resolved. If tab is pressed when the numeric input field is focused, the change
event is only triggered when the value is modified (good). The change
event is (however) triggered each time the ENTER
key is pressed regardless if the value wsa changed or not (may be good - not sure).
I ran npm test
with the latest version 4.4.0 and I do get one test failure...
TouchSpin Tests › should fire the change event only once when updating the value using the keyboard and pressing TAB
expect(received).toBe(expected) // Object.is equality
Expected: 1
Received: 2
103 | const changeEventCounter = (eventLogContent.match(/testinput1: change\n/g) || []).length;
104 |
> 105 | expect(changeEventCounter).toBe(1);
| ^
106 | });
I managed to resolve this failure by inserting this code into index.html,
<div class="col-md-3">
<label for="testinput3">#testinput3:</label>
<input id="testinput3" type="text" value="0" name="testinput3">
</div>
And replacing testinput1
by testinput3
in the test-html-page.test.js
file on line 103 and line 82.
I cannot figure out why this would make it work.
btw: thank you for introducing me to jest
. Very useful! I may actually start writing some JS tests for my application now :-)
@esapy FYI the code snippet from the failing test doesn't seem to be coming from v4.4.0 as const changeEventCounter = (eventLogContent.match(/testinput1: change\n/g) || []).length;
was replaced with a helper method in the published version: expect(await touchspinHelpers.changeEventCounter(page)).toBe(1);
I think you have tried the latest commit from your own branch (from the PR you have created), as there was one failing test there which I have fixed later in a different branch.
As for Jest, I really like it, but it took me three full days to figure out how to use it with this plugin, and I am not sure if I did everything properly. But it definitely helps to have tests. ChatGPT was helping with making it work :)