Skip to content

Commit

Permalink
fix(input, input-number): no longer removes trailing decimal separator (
Browse files Browse the repository at this point in the history
#7159)

**Related Issue:** #7039 

## Summary

This PR will allow trailing decimal separator while user is editing the
input value in `calcite-input` & `calcite-input-number`

Before the Change:

- If the user removes the `1` value from `0.00001` , the input will be
sanitized and the new value will be `0`
- If the user removes the `1` value from `0.1` , the input will be
sanitized and the new value will be `0`

After the Change:

- If the user removes the `1` value from `0.01` , the input value will
be `0.0`
- If the user removes the `1` value from `0.1` , the input value will be
`0.`
  • Loading branch information
anveshmekala authored Jun 29, 2023
1 parent 122f142 commit 01535cf
Show file tree
Hide file tree
Showing 6 changed files with 354 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,35 @@ describe("calcite-input-number", () => {
expect(Number(await element.getProperty("value"))).toBe(195);
});

it("allows deleting exponentail number from decimal and adding trailing zeros", async () => {
const page = await newE2EPage();
await page.setContent(html`<calcite-input-number></calcite-input-number>`);

const calciteInput = await page.find("calcite-input-number");
const input = await page.find("calcite-input-number >>> input");
await calciteInput.callMethod("setFocus");
await page.waitForChanges();
await typeNumberValue(page, "2.100e10");
await page.waitForChanges();
expect(await calciteInput.getProperty("value")).toBe("2.1e10");
expect(await input.getProperty("value")).toBe("2.1e10");

await page.keyboard.press("Backspace");
await page.waitForChanges();
expect(await calciteInput.getProperty("value")).toBe("2.1e1");
expect(await input.getProperty("value")).toBe("2.1e1");

await page.keyboard.press("Backspace");
await page.waitForChanges();
expect(await calciteInput.getProperty("value")).toBe("2.1");
expect(await input.getProperty("value")).toBe("2.1");

await page.keyboard.type("000");
await page.waitForChanges();
expect(await calciteInput.getProperty("value")).toBe("2.1000");
expect(await input.getProperty("value")).toBe("2.1000");
});

it("disallows typing non-numeric characters with shift modifier key down", async () => {
const page = await newE2EPage();
await page.setContent(html`<calcite-input-number></calcite-input-number>`);
Expand Down Expand Up @@ -1114,6 +1143,80 @@ describe("calcite-input-number", () => {
expect(await calciteInput.getProperty("value")).toBe(assertedValue);
expect(await internalLocaleInput.getProperty("value")).toBe(numberStringFormatter.localize(assertedValue));
});

it(`should be able to append values after Backspace for ${locale} locale`, async () => {
const page = await newE2EPage();
await page.setContent(`
<calcite-input-number lang="${locale}"></calcite-input-number>
`);

numberStringFormatter.numberFormatOptions = {
locale,
numberingSystem: "latn",
useGrouping: false
};
const decimalSeparator = numberStringFormatter.decimal;
const calciteInput = await page.find("calcite-input-number");
const input = await page.find("calcite-input-number >>> input");
await calciteInput.callMethod("setFocus");
await typeNumberValue(page, `0${decimalSeparator}0000`);
await page.waitForChanges();
expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0000`);

await page.keyboard.press("Backspace");
await typeNumberValue(page, "1");
await page.waitForChanges();
expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0001`);

await typeNumberValue(page, "01");
await page.waitForChanges();
expect(await input.getProperty("value")).toBe(`0${decimalSeparator}000101`);
});

it(`should keep leading decimal separator while input is focused on Backspace ${locale} locale `, async () => {
const page = await newE2EPage();
await page.setContent(`
<calcite-input-number lang="${locale}"></calcite-input-number>
`);

numberStringFormatter.numberFormatOptions = {
locale,
numberingSystem: "latn",
useGrouping: false
};
const decimalSeparator = numberStringFormatter.decimal;
const calciteInput = await page.find("calcite-input-number");
const input = await page.find("calcite-input-number >>> input");
await calciteInput.callMethod("setFocus");
await typeNumberValue(page, `0${decimalSeparator}01`);
await page.waitForChanges();
expect(await input.getProperty("value")).toBe(`0${decimalSeparator}01`);

await page.keyboard.press("Backspace");
await page.waitForChanges();
expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0`);

await page.keyboard.press("Backspace");
await page.waitForChanges();
expect(await input.getProperty("value")).toBe(`0${decimalSeparator}`);

await typeNumberValue(page, "01");
await page.waitForChanges();
expect(await input.getProperty("value")).toBe(`0${decimalSeparator}01`);
});

it(`should sanitize leading decimal zeros on initial render ${locale} locale`, async () => {
const page = await newE2EPage();
await page.setContent(html`<calcite-input-number value="0.0000" lang="${locale}"></calcite-input-number>`);

numberStringFormatter.numberFormatOptions = {
locale,
numberingSystem: "latn",
useGrouping: false
};
const input = await page.find("calcite-input-number >>> input");
expect(await input.getProperty("value")).toBe("0");
});
});
});

Expand Down Expand Up @@ -1373,7 +1476,7 @@ describe("calcite-input-number", () => {

await page.keyboard.press("Backspace");
await page.waitForChanges();
expect(await element.getProperty("value")).toBe("1");
expect(await element.getProperty("value")).toBe("1.");
expect(calciteInputNumberInput).toHaveReceivedEventTimes(1);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ import {
} from "../../utils/loadable";
import {
connectLocalized,
defaultNumberingSystem,
disconnectLocalized,
LocalizedComponent,
NumberingSystem,
numberStringFormatter
} from "../../utils/locale";
import {
addLocalizedTrailingDecimalZeros,
BigDecimal,
isValidNumber,
parseNumberString,
Expand Down Expand Up @@ -840,12 +840,11 @@ export class InputNumber
useGrouping: this.groupSeparator
};

const sanitizedValue = sanitizeNumberString(
// no need to delocalize a string that ia already in latn numerals
(this.numberingSystem && this.numberingSystem !== "latn") || defaultNumberingSystem !== "latn"
? numberStringFormatter.delocalize(value)
: value
);
const isValueDeleted =
this.previousValue?.length > value.length || this.value?.length > value.length;
const hasTrailingDecimalSeparator = value.charAt(value.length - 1) === ".";
const sanitizedValue =
hasTrailingDecimalSeparator && isValueDeleted ? value : sanitizeNumberString(value);

const newValue =
value && !sanitizedValue
Expand All @@ -854,8 +853,21 @@ export class InputNumber
: ""
: sanitizedValue;

const newLocalizedValue = numberStringFormatter.localize(newValue);
this.localizedValue = newLocalizedValue;
let newLocalizedValue = numberStringFormatter.localize(newValue);

if (origin !== "connected" && !hasTrailingDecimalSeparator) {
newLocalizedValue = addLocalizedTrailingDecimalZeros(
newLocalizedValue,
newValue,
numberStringFormatter
);
}

// adds localized trailing decimal separator
this.localizedValue =
hasTrailingDecimalSeparator && isValueDeleted
? `${newLocalizedValue}${numberStringFormatter.decimal}`
: newLocalizedValue;

this.setPreviousNumberValue(previousValue ?? this.value);
this.previousValueOrigin = origin;
Expand Down
105 changes: 104 additions & 1 deletion packages/calcite-components/src/components/input/input.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1055,6 +1055,35 @@ describe("calcite-input", () => {
expect(Number(await element.getProperty("value"))).toBe(195);
});

it("allows deleting exponentail number from decimal and adding trailing zeros", async () => {
const page = await newE2EPage();
await page.setContent(html`<calcite-input type="number"></calcite-input>`);

const calciteInput = await page.find("calcite-input");
const input = await page.find("calcite-input >>> input");
await calciteInput.callMethod("setFocus");
await page.waitForChanges();
await typeNumberValue(page, "2.100e10");
await page.waitForChanges();
expect(await calciteInput.getProperty("value")).toBe("2.1e10");
expect(await input.getProperty("value")).toBe("2.1e10");

await page.keyboard.press("Backspace");
await page.waitForChanges();
expect(await calciteInput.getProperty("value")).toBe("2.1e1");
expect(await input.getProperty("value")).toBe("2.1e1");

await page.keyboard.press("Backspace");
await page.waitForChanges();
expect(await calciteInput.getProperty("value")).toBe("2.1");
expect(await input.getProperty("value")).toBe("2.1");

await page.keyboard.type("000");
await page.waitForChanges();
expect(await calciteInput.getProperty("value")).toBe("2.1000");
expect(await input.getProperty("value")).toBe("2.1000");
});

it("disallows typing any non-numeric characters with shift modifier key down", async () => {
const page = await newE2EPage();
await page.setContent(html`<calcite-input type="number"></calcite-input>`);
Expand Down Expand Up @@ -1291,6 +1320,80 @@ describe("calcite-input", () => {
expect(await calciteInput.getProperty("value")).toBe(assertedValue);
expect(await internalLocaleInput.getProperty("value")).toBe(localizedValue);
});

it(`should be able to append values after Backspace for ${locale} locale`, async () => {
const page = await newE2EPage();
await page.setContent(`
<calcite-input lang="${locale}" type="number"></calcite-input>
`);

numberStringFormatter.numberFormatOptions = {
locale,
numberingSystem: "latn",
useGrouping: false
};
const decimalSeparator = numberStringFormatter.decimal;
const calciteInput = await page.find("calcite-input");
const input = await page.find("calcite-input >>> input");
await calciteInput.callMethod("setFocus");
await typeNumberValue(page, `0${decimalSeparator}0000`);
await page.waitForChanges();
expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0000`);

await page.keyboard.press("Backspace");
await typeNumberValue(page, "1");
await page.waitForChanges();
expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0001`);

await typeNumberValue(page, "01");
await page.waitForChanges();
expect(await input.getProperty("value")).toBe(`0${decimalSeparator}000101`);
});

it(`should keep leading decimal separator while input is focused on Backspace ${locale} locale `, async () => {
const page = await newE2EPage();
await page.setContent(`
<calcite-input lang="${locale}" type="number"></calcite-input>
`);

numberStringFormatter.numberFormatOptions = {
locale,
numberingSystem: "latn",
useGrouping: false
};
const decimalSeparator = numberStringFormatter.decimal;
const calciteInput = await page.find("calcite-input");
const input = await page.find("calcite-input >>> input");
await calciteInput.callMethod("setFocus");
await typeNumberValue(page, `0${decimalSeparator}01`);
await page.waitForChanges();
expect(await input.getProperty("value")).toBe(`0${decimalSeparator}01`);

await page.keyboard.press("Backspace");
await page.waitForChanges();
expect(await input.getProperty("value")).toBe(`0${decimalSeparator}0`);

await page.keyboard.press("Backspace");
await page.waitForChanges();
expect(await input.getProperty("value")).toBe(`0${decimalSeparator}`);

await typeNumberValue(page, "01");
await page.waitForChanges();
expect(await input.getProperty("value")).toBe(`0${decimalSeparator}01`);
});

it(`should sanitize leading decimal zeros on initial render ${locale} locale`, async () => {
const page = await newE2EPage();
await page.setContent(html`<calcite-input value="0.0000" lang="${locale}" type="number"></calcite-input>`);

numberStringFormatter.numberFormatOptions = {
locale,
numberingSystem: "latn",
useGrouping: false
};
const input = await page.find("calcite-input >>> input");
expect(await input.getProperty("value")).toBe("0");
});
});
});

Expand Down Expand Up @@ -1551,7 +1654,7 @@ describe("calcite-input", () => {

await page.keyboard.press("Backspace");
await page.waitForChanges();
expect(await element.getProperty("value")).toBe("1");
expect(await element.getProperty("value")).toBe("1.");
expect(calciteInputInput).toHaveReceivedEventTimes(1);
});

Expand Down
31 changes: 21 additions & 10 deletions packages/calcite-components/src/components/input/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ import {
} from "../../utils/loadable";
import {
connectLocalized,
defaultNumberingSystem,
disconnectLocalized,
LocalizedComponent,
NumberingSystem,
numberStringFormatter
} from "../../utils/locale";

import {
addLocalizedTrailingDecimalZeros,
BigDecimal,
isValidNumber,
parseNumberString,
Expand Down Expand Up @@ -975,13 +975,11 @@ export class Input
signDisplay: "never"
};

const sanitizedValue = sanitizeNumberString(
// no need to delocalize a string that ia already in latn numerals
(this.numberingSystem && this.numberingSystem !== "latn") ||
defaultNumberingSystem !== "latn"
? numberStringFormatter.delocalize(value)
: value
);
const isValueDeleted =
this.previousValue?.length > value.length || this.value?.length > value.length;
const hasTrailingDecimalSeparator = value.charAt(value.length - 1) === ".";
const sanitizedValue =
hasTrailingDecimalSeparator && isValueDeleted ? value : sanitizeNumberString(value);

const newValue =
value && !sanitizedValue
Expand All @@ -990,8 +988,21 @@ export class Input
: ""
: sanitizedValue;

const newLocalizedValue = numberStringFormatter.localize(newValue);
this.localizedValue = newLocalizedValue;
let newLocalizedValue = numberStringFormatter.localize(newValue);

if (origin !== "connected" && !hasTrailingDecimalSeparator) {
newLocalizedValue = addLocalizedTrailingDecimalZeros(
newLocalizedValue,
newValue,
numberStringFormatter
);
}

// adds localized trailing decimal separator
this.localizedValue =
hasTrailingDecimalSeparator && isValueDeleted
? `${newLocalizedValue}${numberStringFormatter.decimal}`
: newLocalizedValue;

this.userChangedValue = origin === "user" && this.value !== newValue;
// don't sanitize the start of negative/decimal numbers, but
Expand Down
Loading

0 comments on commit 01535cf

Please sign in to comment.