From 3e121cc9537b36812bc7848b7091fae4b2881cc5 Mon Sep 17 00:00:00 2001 From: nathan Date: Tue, 3 Sep 2024 15:22:53 -0600 Subject: [PATCH] Fix numbers got wrecked on blur Numbers with , as decimal separator were being re-parsed incorrectly on blur, ruining what the user just input --- api/js/etemplate/Et2Date/Et2DateDuration.ts | 2 +- api/js/etemplate/Et2Textbox/Et2Number.ts | 42 ++++++++++--------- api/js/etemplate/Et2Textbox/Et2Textbox.ts | 4 ++ .../Et2Textbox/test/Et2Number.test.ts | 5 ++- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/api/js/etemplate/Et2Date/Et2DateDuration.ts b/api/js/etemplate/Et2Date/Et2DateDuration.ts index 65d29a82f5..5671a60210 100644 --- a/api/js/etemplate/Et2Date/Et2DateDuration.ts +++ b/api/js/etemplate/Et2Date/Et2DateDuration.ts @@ -313,7 +313,7 @@ export class Et2DateDuration extends Et2InputWidget(LitElement) { for(let i = this._durationNode.length; --i >= 0;) { - value += parseInt(this._durationNode[i].value) * this._unit2seconds(this._durationNode[i].name); + value += this._durationNode[i].valueAsNumber * this._unit2seconds(this._durationNode[i].name); } if(this.dataFormat !== 's') { diff --git a/api/js/etemplate/Et2Textbox/Et2Number.ts b/api/js/etemplate/Et2Textbox/Et2Number.ts index a8bb5199e9..2313eff17c 100644 --- a/api/js/etemplate/Et2Textbox/Et2Number.ts +++ b/api/js/etemplate/Et2Textbox/Et2Number.ts @@ -9,7 +9,7 @@ */ import {Et2Textbox} from "./Et2Textbox"; -import {css, html, nothing, render} from "lit"; +import {css, html, nothing, PropertyValues, render} from "lit"; import {customElement} from "lit/decorators/custom-element.js"; import {property} from "lit/decorators/property.js"; @@ -150,6 +150,10 @@ export class Et2Number extends Et2Textbox // Add spinners render(this._incrementButtonTemplate(), this); + if(this.value) + { + this.value = formatNumber(this.value, this.decimalSeparator, this.thousandsSeparator, this.precision); + } } firstUpdated() @@ -170,6 +174,14 @@ export class Et2Number extends Et2Textbox }); } + willUpdate(changedProperties : PropertyValues) + { + if(this._mask && Object.keys(this.maskOptions).filter(v => changedProperties.has(v)).length > 0) + { + this._mask.updateOptions(this.maskOptions); + } + } + transformAttributes(attrs) { if(attrs.precision === 0 && typeof attrs.step === 'undefined') @@ -237,7 +249,6 @@ export class Et2Number extends Et2Textbox val = this.min; } super.value = formatNumber(val, this.decimalSeparator, this.thousandsSeparator, this.precision); - this.updateMaskValue(); } get value() : string @@ -245,6 +256,13 @@ export class Et2Number extends Et2Textbox return super.value; } + protected updateMaskValue() + {} + + /** + * Value returned to server is always no thousands separator, "." decimal separator + * @returns {any} + */ getValue() : any { if(this.value == "" || typeof this.value == "undefined") @@ -257,8 +275,7 @@ export class Et2Number extends Et2Textbox get valueAsNumber() : number { - this.updateMaskValue(); - let formattedValue = (this._mask?.value ? this.stripFormat(this._mask.value) : this._mask?.unmaskedValue) ?? this.value; + let formattedValue : string | number = "" + this.stripFormat(this.value); if(formattedValue == "") { return 0; @@ -345,21 +362,6 @@ export class Et2Number extends Et2Textbox return options; } - updateMaskValue() - { - this._mask?.updateValue(); - if(!this.mask && this._mask) - { - // Number mask sometimes gets lost with different decimal characters - this._mask.unmaskedValue = ("" + this.value); - } - - if(this.value !== "" && this._mask) - { - this._mask.value = formatNumber(this.value, this.decimalSeparator, this.thousandsSeparator, this.precision); - } - this._mask?.updateValue(); - } private handleScroll(e) @@ -409,7 +411,7 @@ export class Et2Number extends Et2Textbox * @param {number} value * @returns {string} */ -export function formatNumber(value : number, decimalSeparator : string = ".", thousandsSeparator : string = "", decimalPlaces = undefined) : string +export function formatNumber(value : string | number, decimalSeparator : string = ".", thousandsSeparator : string = "", decimalPlaces = undefined) : string { // Split by . because value is a number, so . is decimal separator let parts = ("" + value).split("."); diff --git a/api/js/etemplate/Et2Textbox/Et2Textbox.ts b/api/js/etemplate/Et2Textbox/Et2Textbox.ts index fdbb79ae10..c05c5a603b 100644 --- a/api/js/etemplate/Et2Textbox/Et2Textbox.ts +++ b/api/js/etemplate/Et2Textbox/Et2Textbox.ts @@ -202,6 +202,10 @@ export class Et2Textbox extends Et2InputWidget(SlInput) protected updateMaskValue() { + if(!this._mask) + { + return; + } this._mask.unmaskedValue = "" + this.value; this._mask.updateValue(); this.updateComplete.then(() => diff --git a/api/js/etemplate/Et2Textbox/test/Et2Number.test.ts b/api/js/etemplate/Et2Textbox/test/Et2Number.test.ts index 3f70e632b1..7f09b6f4de 100644 --- a/api/js/etemplate/Et2Textbox/test/Et2Number.test.ts +++ b/api/js/etemplate/Et2Textbox/test/Et2Number.test.ts @@ -83,13 +83,14 @@ describe("Number widget", () => expected = set; } element.value = set; - assert.equal(element.value, expected); + assert.equal(element.getValue(), expected); }; it("Handles . as decimal", () => { window.egw.preference = () => "."; + element.decimalSeparator = "."; checkValue("1"); assert.equal(element.valueAsNumber, 1, "Numeric value does not match"); @@ -102,10 +103,12 @@ describe("Number widget", () => it("Handles , as decimal", () => { window.egw.preference = () => ","; + element.decimalSeparator = ","; checkValue("1"); assert.equal(element.valueAsNumber, 1, "Numeric value does not match"); checkValue("1,1", "1.1"); + assert.equal(element.getValue(), "1.1"); assert.equal(element.valueAsNumber, 1.1, "Numeric value does not match"); element.value = "Fail";