Reputation: 353
I am making an observer that adds a thousands separator, be it a '.' or a ',', to whatever number the user types.
For those who don't know, in Polymer it's possible to bind an observer to a property which is basically a function called everytime that property changes.
The observer is called with two parameters, 'newValue' and 'oldValue' pretty self-explanatory parameters names.
Right now it adds the separators correctly but when I press delete it doesn't delete what it's supposed to delete.
This is my use case:
1) I type '123456'.
2) The code changes it to '123.456'.
3) I press delete with the cursor at the last position '123.456|'.
4) The observer is called three times.
The first one with 'newValue' = '123.45'. The property and the number displayed are updated to '12.345'.
As the property has been changed, the observer is called a second time with 'newValue' = '12.345'. The property and the number displayed are updated to the same val (I don't know why, it hasn't been changed per se.... but lets continue).
This time the observer is called AGAIN , which is strange as it has the same value as before. The 'newValue' is equal to '123.456' (something I don't understand) and the property and number displayed returns to the initial state (see step 2).
I first started using the property observer but as I came up with this problem I switched to using an on-input listener as it lets me check the inputType property and act accordingly.
When the action is delete the inputType is 'contentDeleteBackward' and when it is insert the inputType is 'insertText'.
This is the observer function
_turnoverObserver: function (newValue, oldValue) {
let parsedWithoutCommas = String(parseInt(newValue.replace(/\D/g, ''), 10));
if (parsedWithoutCommas !== oldValue) {
this.fire('turnover-event', {turnover: parsedWithoutCommas});
let result = [];
let reversed = parsedWithoutCommas.split("").reverse();
if (reversed.length > 3) {
reversed.forEach((digit, index) => {
if (index !== 0 && index % 3 === 0) {
result.push('.');
}
result.push(digit);
});
this.turnover = result.reverse().join("");
}
}
},
This is the on-input listener function
_addSeparatorTurnover (e) {
let value = e.target.value;
let parsedWithoutCommas = String(parseInt(value.replace(/\D/g, ''), 10));
if (e.inputType === 'insertText') {
let result = [];
if (parsedWithoutCommas.length > 3) {
let reversed = parsedWithoutCommas.split('').reverse();
reversed.forEach((num, index) => {
if (index !== 0 && index % 3 === 0) {
result.push('.');
}
result.push(num);
});
e.target.value = result.reverse().join('');
}
} else {
let result = [];
let {selectionStart, selectionEnd} = e.target.$.input;
let deletedVal = parsedWithoutCommas.slice(0, selectionStart - 2) + parsedWithoutCommas.slice(selectionStart - 1);
deletedVal.split('').reverse().forEach((num, index) => {
if (index !== 0 && index % 3 === 0) {
result.push('.');
}
result.push(num);
});
e.target.value = result.reverse().join('');
}
},
Typing '123456' should display '123.456'
Deleting the last digit from '123.456' should change it to '12.345'
Upvotes: 0
Views: 280
Reputation: 171
I tried using your code and could see that the observer over the property is calling exactly twice and not thrice as you mentioned. However, I have commented the below line from your code.
`this.fire('turnover-event', {turnover: parsedWithoutCommas});`
There is a chance that you might be trying to change the same value even in the above event and probably causing the third call. Also, you code seems to work properly while inserting the numbers. If we start deleting the numbers, it would stop working as expected below 4 digits. i.e., For 4 digits it show 1.234 and if you delete one more it shows 1.23 which is not correct as per your expectations(assuming). I tweaked your code and below is working perfectly.
_turnoverObserver: function(newValue, oldValue) {
if (newValue) {
let parsedWithoutCommas = String(parseInt(newValue.replace(/\D/g, ''), 10));
if (parsedWithoutCommas !== oldValue) {
//this.fire('turnover-event', { turnover: parsedWithoutCommas });
let result = [];
let reversed = parsedWithoutCommas.split("").reverse();
if (reversed.length >= 3) {
reversed.forEach((digit, index) => {
if (index !== 0 && index % 3 === 0) {
result.push('.');
}
result.push(digit);
});
this.somevalue = result.reverse().join("");
}
}
}
}
Upvotes: 2