Skip to content

Commit

Permalink
fix(number-field): fix step=any to support integer and decimal number (
Browse files Browse the repository at this point in the history
…#485)

* docs(number-field): add docs for step any

* fix(number-field): fix step any to support min following native behavior

Co-authored-by: Wasuwat Limsuparhat <[email protected]>
Co-authored-by: Sarin Udompanish
  • Loading branch information
Theeraphat-Sorasetsakul and wsuwt authored Oct 7, 2022
1 parent 6adb42c commit 13bbb34
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 6 deletions.
4 changes: 3 additions & 1 deletion documents/src/pages/elements/number-field.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,16 @@ document.getElementById('mm').value = '-15';
```

## Set input step
The step attribute specifies the interval between valid numbers. For instance, when `step="2"`, valid values Would only be even numbers e.g. 2,4,6,8....
The step attribute specifies the interval between valid numbers. For instance, when `step="2"`, valid values Would only be even numbers e.g. 2,4,6,8... Alternatively, specify the `step="any"` to allow any value.

::
```javascript
::number-field::
```
```html
<ef-number-field placeholder="Even numbers only" step="2"></ef-number-field>

<ef-number-field placeholder="Step any allow any number" step="any"></ef-number-field>
```
::

Expand Down
1 change: 1 addition & 0 deletions packages/elements/src/number-field/__demo__/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
<p><ef-number-field placeholder="Step = 2" min="1" step="2" max="8"></ef-number-field></p>
<p><ef-number-field placeholder="Step = 0.01" min="-1" step="0.01" max="1"></ef-number-field></p>
<p><ef-number-field placeholder="Step = 0.001" min="-1" step="0.001" max="1"></ef-number-field></p>
<p><ef-number-field placeholder="Step = any" step="any"></ef-number-field></p>
</demo-block>

<demo-block layout="normal" header="Min & Max" tags="validation">
Expand Down
77 changes: 77 additions & 0 deletions packages/elements/src/number-field/__test__/number-field.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -851,5 +851,82 @@ describe('number-field/NumberField', () => {

expect(el.value).to.equal('1.5');
});

describe('Step="any"', () => {
it('Factor should be 1 when step up', async () => {
el.setAttribute('step', 'any');
el.setAttribute('value', '-1.86');
await elementUpdated();

setTimeout(() => dispatchTapEvent(spinnerUpEl));
await oneEvent(spinnerUpEl, 'tap');
expect(el.value).to.equal('-0.86', 'Value should be increase by 1 and decimal value should keep stay');

setTimeout(() => dispatchTapEvent(spinnerUpEl));
await oneEvent(spinnerUpEl, 'tap');
expect(el.value).to.equal('0.14', 'Value should be increase by 1 and decimal value should keep stay');

setTimeout(() => dispatchTapEvent(spinnerUpEl));
await oneEvent(spinnerUpEl, 'tap');
expect(el.value).to.equal('1.14', 'Value should be increase by 1 and decimal value should keep stay');
});
it('Factor should be 1 when step down', async () => {
el.setAttribute('step', 'any');
el.setAttribute('value', '1.86');
await elementUpdated();

setTimeout(() => dispatchTapEvent(spinnerDownEl));
await oneEvent(spinnerDownEl, 'tap');
expect(el.value).to.equal('0.86', 'Value should be decrease by 1 and decimal value should keep stay');

setTimeout(() => dispatchTapEvent(spinnerDownEl));
await oneEvent(spinnerDownEl, 'tap');
expect(el.value).to.equal('-0.14', 'Value should be decrease by 1 and decimal value should keep stay');

setTimeout(() => dispatchTapEvent(spinnerDownEl));
await oneEvent(spinnerDownEl, 'tap');
expect(el.value).to.equal('-1.14', 'Value should be decrease by 1 and decimal value should keep stay');
});
it('Should be decreased to min if value is decimal and min is integer', async () => {
el.setAttribute('step', 'any');
el.setAttribute('value', '1.86');
el.setAttribute('min', '1');
await elementUpdated();

setTimeout(() => dispatchTapEvent(spinnerDownEl));
await oneEvent(spinnerDownEl, 'tap');
expect(el.value).to.equal('1', 'Follow by native behavior that value should decrease when min is integer.');
});
it('Should not be decreased to min if value is decimal and min is decimal', async () => {
el.setAttribute('step', 'any');
el.setAttribute('value', '1.86');
el.setAttribute('min', '1.1');
await elementUpdated();

setTimeout(() => dispatchTapEvent(spinnerDownEl));
await oneEvent(spinnerDownEl, 'tap');
expect(el.value).to.equal('1.86', 'Follow by native behavior that value should decrease when min is decimal.');
});
it('Should not be increased to max if value is decimal and max is integer', async () => {
el.setAttribute('step', 'any');
el.setAttribute('value', '1.86');
el.setAttribute('max', '2');
await elementUpdated();

setTimeout(() => dispatchTapEvent(spinnerUpEl));
await oneEvent(spinnerUpEl, 'tap');
expect(el.value).to.equal('1.86', 'Follow by native behavior that value should increase when max is integer.');
});
it('Should not be increased to max if value is decimal and max is decimal', async () => {
el.setAttribute('step', 'any');
el.setAttribute('value', '1.86');
el.setAttribute('max', '2.1');
await elementUpdated();

setTimeout(() => dispatchTapEvent(spinnerUpEl));
await oneEvent(spinnerUpEl, 'tap');
expect(el.value).to.equal('1.86', 'Follow by native behavior that value should increase when max is integer.');
});
});
});
});
17 changes: 12 additions & 5 deletions packages/elements/src/number-field/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,9 @@ export class NumberField extends FormFieldElement {
* @returns true if value is integral
*/
private isValueIntegralMultipleOfStep (value: number): boolean {
if (this.step === ANY_STEP) {
return true;
}
const decimals = Math.max(this.getDecimalPlace(value), this.stepDecimals);
const division = (this.stepBase - value) / this.getAllowedValueStep();
const number = decimals ? this.toFixedNumber(division, decimals) : division;
Expand Down Expand Up @@ -621,23 +624,27 @@ export class NumberField extends FormFieldElement {
// step-up or step-down
if (this.isValueIntegralMultipleOfStep(value)) {
const delta = allowedValueStep * stepIncrement * direction;
value += delta;
value = this.toFixedNumber(value + delta, Math.max(this.getDecimalPlace(value), this.getDecimalPlace(delta)));
}
else {
value = this.findNearestSteppedValue(valueBeforeStepping, stepBase, allowedValueStep, direction);
}

// Follow native number field with step "any".
// When set min as a decimal number, value should't be decreased to min
if (value < min && this.step === ANY_STEP && this.getDecimalPlace(this.stringToNumber(this.min)) > 0) {
value = valueBeforeStepping;
}
// If the element has a minimum, and value is less than that minimum,
// then set value to the smallest value that, when subtracted from the step base,
// is an integral multiple of the allowed value step, and that is more than or equal to minimum.
if (value < min) {
else if (value < min) {
value = this.findNearestSteppedValue(min + allowedValueStep, stepBase, allowedValueStep, Direction.Down);
}

// If the element has a maximum, and value is greater than that maximum,
// then set value to the largest value that, when subtracted from the step base,
// is an integral multiple of the allowed value step, and that is less than or equal to maximum.
if (value > max) {
else if (value > max) {
value = this.findNearestSteppedValue(max - allowedValueStep, stepBase, allowedValueStep, Direction.Up);
}

Expand All @@ -647,7 +654,7 @@ export class NumberField extends FormFieldElement {
return;
}

this.inputValue = `${this.toFixedNumber(value)}`;
this.inputValue = String(value);
}

/**
Expand Down

0 comments on commit 13bbb34

Please sign in to comment.