Skip to content

Commit e6cdd83

Browse files
committed
fix: clear a number input to no value instead of zero
1 parent 25d3faf commit e6cdd83

3 files changed

Lines changed: 38 additions & 1 deletion

File tree

‎adminforth/spa/src/afcl/Input.vue‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
ref="input"
1313
v-bind="$attrs"
1414
:type="type"
15-
@input="$emit('update:modelValue', type === 'number' ? Number(($event.target as HTMLInputElement)?.value) : ($event.target as HTMLInputElement)?.value)"
15+
@input="$emit('update:modelValue', type === 'number' ? numberInputValue(($event.target as HTMLInputElement)?.value) : ($event.target as HTMLInputElement)?.value)"
1616
:value="modelValue"
1717
aria-describedby="helper-text-explanation"
1818
class="afcl-input inline-flex bg-lightInputBackground text-lightInputText dark:text-darkInputText border border-lightInputBorder rounded-0 focus:ring-lightPrimary focus:border-lightPrimary dark:focus:ring-darkPrimary dark:focus:border-darkPrimary
@@ -37,6 +37,7 @@
3737
3838
import { ref } from 'vue';
3939
import { useCoreStore } from '@/stores/core';
40+
import { numberInputValue } from './inputValue';
4041
4142
const coreStore = useCoreStore();
4243
const isIos = coreStore.isIos;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Number('') is 0, so an emptied field would store a real zero
2+
export function numberInputValue(raw: string | undefined | null): number | null {
3+
if (raw == null || raw.trim() === '') {
4+
return null;
5+
}
6+
const value = Number(raw);
7+
return Number.isNaN(value) ? null : value;
8+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import fs from 'node:fs/promises';
2+
import path from 'node:path';
3+
import { fileURLToPath } from 'node:url';
4+
import { numberInputValue } from '../../adminforth/spa/src/afcl/inputValue';
5+
6+
describe('afcl Input number value', () => {
7+
it.each([[''], [' ']])('reports an emptied field as no value, not zero (%p)', (raw) => {
8+
expect(numberInputValue(raw)).toBeNull();
9+
});
10+
11+
it('reports a value the browser cannot parse as no value', () => {
12+
expect(numberInputValue('abc')).toBeNull();
13+
});
14+
15+
it('keeps a real number, including zero the user actually typed', () => {
16+
expect(numberInputValue('0')).toBe(0);
17+
expect(numberInputValue('42')).toBe(42);
18+
expect(numberInputValue('-3.5')).toBe(-3.5);
19+
});
20+
});
21+
22+
it('the component routes its number branch through the helper', async () => {
23+
const component = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../adminforth/spa/src/afcl/Input.vue');
24+
const source = await fs.readFile(component, 'utf8');
25+
26+
expect(source).toMatch(/type === 'number' \? numberInputValue\(/);
27+
expect(source).not.toMatch(/type === 'number' \? Number\(/);
28+
});

0 commit comments

Comments
 (0)