Skip to content

Commit

Permalink
Merge pull request #3035 from brampeirs/number-input-validation
Browse files Browse the repository at this point in the history
feat: enhance increment and decrement functionality number component
  • Loading branch information
zvonimirfras authored Oct 31, 2024
2 parents 8852b11 + 9ebc8ae commit c20472b
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 5 deletions.
46 changes: 46 additions & 0 deletions src/number-input/number.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,29 @@ describe("Number", () => {
buttonUp.click();
fixture.detectChanges();
expect(component.value).toEqual(2);
});

it("should increment and set value to max if value + step exceeds max", () => {
fixture.detectChanges();
buttonUp = fixture.debugElement.query(By.css(".up-icon")).nativeElement;
component.value = 95;
component.step = 10;
component.max = 100;
buttonUp.click();
fixture.detectChanges();
expect(component.value).toEqual(100);
});

it("should increment and set value to min if value + step is less than min", () => {
fixture.detectChanges();
buttonUp = fixture.debugElement.query(By.css(".up-icon")).nativeElement;
component.value = 0;
component.step = 2;
component.min = 5;
buttonUp.click();
fixture.detectChanges();

expect(component.value).toBe(5);
});

it("should not increment value if max is reached", () => {
Expand All @@ -129,6 +152,29 @@ describe("Number", () => {
expect(component.value).toEqual(0);
});

it("should decrement and set value to max if value - step exceeds max", () => {
fixture.detectChanges();
buttonUp = fixture.debugElement.query(By.css(".down-icon")).nativeElement;
component.value = 20;
component.step = 2;
component.max = 15;
buttonUp.click();
fixture.detectChanges();

expect(component.value).toBe(15);
});

it("should decrement and set value to min if value - step is less than min", () => {
fixture.detectChanges();
buttonUp = fixture.debugElement.query(By.css(".down-icon")).nativeElement;
component.value = 6;
component.step = 2;
component.min = 5;
buttonUp.click();
fixture.detectChanges();
expect(component.value).toEqual(5);
});

it("should not decrement value min is reached", () => {
fixture.detectChanges();
buttonUp = fixture.debugElement.query(By.css(".down-icon")).nativeElement;
Expand Down
34 changes: 34 additions & 0 deletions src/number-input/number.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,23 @@ export class NumberComponent implements ControlValueAccessor {
* Adds `step` to the current `value`.
*/
onIncrement(): void {
// if max is set and value + step is greater than max, set value to max
// example: max = 100, step = 10, value = 95 , value + step = 105, value will be set to 100 (max) instead of 105
if (this.max !== null && this.value + this.step > this.max) {
this.value = this.max;
this.emitChangeEvent();
return;
}

// if min is set and value + step is less than min, set value to min
// example: min = 5, step = 2, value = 0, value + step = 2, value will be set to 5 (min) instead of 2
if (this.min !== null && this.value + this.step < this.min) {
this.value = this.min;
this.emitChangeEvent();
return;
}

// if max is not set or value + step is less than max, increment value by step
if (this.max === null || this.value + this.step <= this.max) {
this.value += this.step;
this.value = parseFloat(this.value.toPrecision(this.precision));
Expand All @@ -363,6 +380,23 @@ export class NumberComponent implements ControlValueAccessor {
* Subtracts `step` to the current `value`.
*/
onDecrement(): void {
// if max is set and value - step is greater than max, set value to max
// example: max = 15, step = 2, value = 20, value - step = 18, value will be set to 15 (max) instead of 18
if (this.max !== null && this.value - this.step > this.max) {
this.value = this.max;
this.emitChangeEvent();
return;
}

// if min is set and value - step is less than min, set value to min
// example: min = 5, step = 2, value = 6, value - step = 4, value will be set to 5 (min) instead of 4
if (this.min !== null && this.value - this.step < this.min) {
this.value = this.min;
this.emitChangeEvent();
return;
}

// if min is not set or value - step is greater than min, decrement value by step
if (this.min === null || this.value - this.step >= this.min) {
this.value -= this.step;
this.value = parseFloat(this.value.toPrecision(this.precision));
Expand Down
16 changes: 11 additions & 5 deletions src/number-input/number.stories.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
/* tslint:disable variable-name */

import { moduleMetadata, Meta } from "@storybook/angular";
import { FormsModule } from "@angular/forms";
import { NumberModule, NumberComponent } from "./";

export default {
title: "Components/Number Input",
decorators: [
moduleMetadata({
imports: [NumberModule]
imports: [NumberModule, FormsModule]
})
],
args: {
Expand Down Expand Up @@ -35,7 +36,9 @@ export default {
theme: {
options: ["light", "dark"],
control: "radio"
}
},
// Actions
change: { action: 'changed'}
},
component: NumberComponent
} as Meta;
Expand All @@ -57,7 +60,8 @@ const Template = (args) => ({
[size]="size"
[readonly]="readonly"
[disabled]="disabled"
[fluid]="fluid">
[fluid]="fluid"
(change)="change($event)">
</cds-number>
`
});
Expand Down Expand Up @@ -86,7 +90,8 @@ const ModelTemplate = (args) => ({
[warnText]="warnText"
[disabled]="disabled"
[(ngModel)]="value"
[fluid]="fluid">
[fluid]="fluid"
(change)="change($event)">
</cds-number>
{{ value }}
`
Expand All @@ -100,7 +105,8 @@ const SkeletonTemplate = (args) => ({
<cds-number
label="Number input label"
skeleton="true"
[fluid]="fluid">
[fluid]="fluid"
(change)="change($event)">
</cds-number>
`
});
Expand Down

0 comments on commit c20472b

Please sign in to comment.