Skip to content

Commit db36317

Browse files
authored
fix(input): Incorrect validation with numeric input and step attribute (#1522)
Closes #1521
1 parent df490fd commit db36317

File tree

5 files changed

+59
-15
lines changed

5 files changed

+59
-15
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1717

1818
### Fixed
1919
- Combo - Rendering issue after Edge browser autofill behavior [#1497](https://github.com/IgniteUI/igniteui-webcomponents/issues/1497)
20+
- Input - Incorrect validation with numeric input and step attribute [#1521](https://github.com/IgniteUI/igniteui-webcomponents/issues/1521)
2021

2122
## [5.1.2] - 2024-11-04
2223
### Added

src/components/common/util.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,16 @@ export const asPercent = (part: number, whole: number) => (part / whole) * 100;
1515
export const clamp = (number: number, min: number, max: number) =>
1616
Math.max(min, Math.min(number, max));
1717

18+
export function numberOfDecimals(number: number): number {
19+
const decimals = last(number.toString().split('.'));
20+
return decimals ? decimals.length : 0;
21+
}
22+
23+
export function roundPrecise(number: number, magnitude = 1): number {
24+
const factor = 10 ** magnitude;
25+
return Math.round(number * factor) / factor;
26+
}
27+
1828
export function numberInRangeInclusive(
1929
value: number,
2030
min: number,

src/components/common/validators.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import { DateTimeUtil } from '../date-time-input/date-util.js';
22
import validatorMessages from './localization/validation-en.js';
3-
import { asNumber, formatString, isDefined } from './util.js';
3+
import {
4+
asNumber,
5+
formatString,
6+
isDefined,
7+
numberOfDecimals,
8+
roundPrecise,
9+
} from './util.js';
410

511
type ValidatorHandler<T> = (host: T) => boolean;
612
type ValidatorMessageFormat<T> = (host: T) => string;
@@ -93,10 +99,20 @@ export const stepValidator: Validator<{
9399
}> = {
94100
key: 'stepMismatch',
95101
message: 'Value does not conform to step constraint',
96-
isValid: ({ min, step, value }) =>
97-
isDefined(value) && value !== '' && isDefined(step)
98-
? (asNumber(value) - asNumber(min)) % asNumber(step, 1) === 0
99-
: true,
102+
isValid: ({ min, step, value }) => {
103+
if (isDefined(value) && value !== '' && isDefined(step)) {
104+
const _value = asNumber(value) - asNumber(min);
105+
const _step = asNumber(step);
106+
const magnitude = numberOfDecimals(_step) + 1;
107+
const rem = roundPrecise(
108+
Math.abs(_value - _step * Math.round(_value / _step)),
109+
magnitude
110+
);
111+
112+
return !rem;
113+
}
114+
return true;
115+
},
100116
};
101117

102118
export const emailValidator: Validator<{ value: string }> = {

src/components/input/input.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,30 @@ describe('Input component', () => {
356356
});
357357
});
358358

359+
describe('issue-1521', () => {
360+
let input: IgcInputComponent;
361+
362+
beforeEach(async () => {
363+
input = await fixture<IgcInputComponent>(html`
364+
<igc-input type="number" step="0.1"></igc-input>
365+
`);
366+
});
367+
368+
it('', () => {
369+
input.value = '1';
370+
expect(input.checkValidity()).to.be.true;
371+
372+
input.value = '1.1';
373+
expect(input.checkValidity()).to.be.true;
374+
375+
input.value = '1.11';
376+
expect(input.checkValidity()).to.be.false;
377+
378+
input.step = 0.01;
379+
expect(input.checkValidity()).to.be.true;
380+
});
381+
});
382+
359383
describe('Form integration', () => {
360384
const spec = createFormAssociatedTestBed<IgcInputComponent>(
361385
html`<igc-input name="input"></igc-input>`

src/components/rating/rating.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ import {
3535
formatString,
3636
isEmpty,
3737
isLTR,
38+
numberOfDecimals,
39+
roundPrecise,
3840
} from '../common/util.js';
3941
import IgcIconComponent from '../icon/icon.js';
4042
import IgcRatingSymbolComponent from './rating-symbol.js';
@@ -328,17 +330,8 @@ export default class IgcRatingComponent extends FormAssociatedMixin(
328330
return clamp(value, this.step, this.max);
329331
}
330332

331-
protected getPrecision(num: number) {
332-
const [_, decimal] = num.toString().split('.');
333-
return decimal ? decimal.length : 0;
334-
}
335-
336333
protected round(value: number) {
337-
return Number(
338-
(Math.round(value / this.step) * this.step).toFixed(
339-
this.getPrecision(this.step)
340-
)
341-
);
334+
return roundPrecise(value, numberOfDecimals(this.step));
342335
}
343336

344337
protected clipSymbol(index: number, isLTR = true) {

0 commit comments

Comments
 (0)