diff --git a/components/stepper/demo/basic.ts b/components/stepper/demo/basic.ts
index 6a735adf..a379b542 100644
--- a/components/stepper/demo/basic.ts
+++ b/components/stepper/demo/basic.ts
@@ -4,25 +4,36 @@ import { Component } from '@angular/core';
selector: 'demo-stepper-basic',
template: `
- Show number value
Show number value
+ Decimal step
Disabled
+ ReadOnly
-
+
+
+
+
-
-
+
+
`,
styles: [``]
})
export class DemoStepperBasicComponent {
- value = 3;
- value1 = 6;
+ value = 0;
+ decimalValue = 6;
constructor() {}
diff --git a/components/stepper/stepper.component.html b/components/stepper/stepper.component.html
index ca390121..78f0b112 100644
--- a/components/stepper/stepper.component.html
+++ b/components/stepper/stepper.component.html
@@ -20,8 +20,9 @@
diff --git a/components/stepper/stepper.component.spec.ts b/components/stepper/stepper.component.spec.ts
index a4c5ad91..7928df9f 100644
--- a/components/stepper/stepper.component.spec.ts
+++ b/components/stepper/stepper.component.spec.ts
@@ -1,7 +1,7 @@
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
-import { ComponentFixture, TestBed, fakeAsync, waitForAsync } from '@angular/core/testing';
+import { ComponentFixture, TestBed, fakeAsync, waitForAsync, tick } from '@angular/core/testing';
import { StepperModule } from './stepper.module';
describe('StepperComponent', () => {
@@ -12,12 +12,14 @@ describe('StepperComponent', () => {
let upButton;
let downButton;
let inputEle;
- beforeEach(waitForAsync(() => {
- TestBed.configureTestingModule({
- declarations: [TestStepperComponent],
- imports: [StepperModule, FormsModule]
- }).compileComponents();
- }));
+ beforeEach(
+ waitForAsync(() => {
+ TestBed.configureTestingModule({
+ declarations: [TestStepperComponent],
+ imports: [StepperModule, FormsModule]
+ }).compileComponents();
+ })
+ );
beforeEach(() => {
fixture = TestBed.createComponent(TestStepperComponent);
@@ -42,7 +44,6 @@ describe('StepperComponent', () => {
'up-disabled'
);
});
-
it('should min work', () => {
component.min = 9;
component.value = 9;
@@ -68,8 +69,7 @@ describe('StepperComponent', () => {
'up-disabled'
);
});
-
- it('should dowDisabled work', () => {
+ it('should downDisabled work', () => {
component.min = 5;
component.value = 9;
component.step = 3;
@@ -83,29 +83,6 @@ describe('StepperComponent', () => {
);
});
- it('should defaultValue work', () => {
- component.defaultValue = 11;
- fixture.detectChanges();
- expect(component.defaultValue).toBe(11, 'value == defaultValue');
- });
- it('should step work', () => {
- component.value = 1e-13;
- component.step = 2;
- fixture.detectChanges();
- downButton.click();
- expect(component.value).toBe(-1.9999999999999, 'step is 2');
- component.step = 3;
- fixture.detectChanges();
- upButton.click();
- expect(component.value).toBe(1.0000000000001, 'step is 3');
- });
-
- it('should showNumber work', () => {
- expect(stepperEle.nativeElement.classList).toContain('showNumber', 'showNumber');
- component.showNumber = false;
- fixture.detectChanges();
- expect(stepperEle.nativeElement.classList).not.toContain('showNumber', 'showNumber is not show');
- });
it('should disabled work', () => {
expect(stepperEle.nativeElement.classList).not.toContain('am-stepper-disabled', 'not contain am-stepper-disabled');
component.disabled = true;
@@ -150,27 +127,79 @@ describe('StepperComponent', () => {
expect(stepperEle.nativeElement.classList).not.toContain('am-stepper-disabled', 'contain am-stepper-disabled');
});
-
it('should readOnly work', fakeAsync(() => {
+ component.readOnly = true;
+ fixture.detectChanges();
+ expect(inputEle.getAttribute('readonly')).not.toBeNull('readonly is null');
+ }));
+
+ it('should defaultValue work', () => {
+ component.defaultValue = 11;
+ fixture.detectChanges();
+ expect(component.defaultValue).toBe(11, 'value == defaultValue');
+ });
+ it('should step work', () => {
+ component.value = 1e-13;
+ component.step = 2;
+ fixture.detectChanges();
+ downButton.click();
+ expect(component.value).toBe(-1.9999999999999, 'step is 2');
+ component.step = 3;
+ fixture.detectChanges();
+ upButton.click();
+ expect(component.value).toBe(1.0000000000001, 'step is 3');
+ });
+ it('should showNumber work', () => {
+ expect(stepperEle.nativeElement.classList).toContain('showNumber', 'showNumber');
+ component.showNumber = false;
+ fixture.detectChanges();
+ expect(stepperEle.nativeElement.classList).not.toContain('showNumber', 'showNumber is not show');
+ });
+
+ it('should only input numbers work', fakeAsync(() => {
+ inputEle.value = 'ssssss';
+ inputEle.dispatchEvent(new UIEvent('input'));
+ tick(0);
+ expect(component.value).toBe(0, 'input ssssss');
+
+ inputEle.value = '测试中文';
+ inputEle.dispatchEvent(new UIEvent('input'));
+ tick(0);
+ expect(component.value).toBe(0, 'input 测试中文');
+
+ inputEle.value = 's1s.s2s.s3s';
+ inputEle.dispatchEvent(new UIEvent('input'));
+ tick(0);
+ expect(component.value).toBe(123, 'input s1s.s2s.s3s');
+
+ inputEle.value = '-1-2-3';
+ inputEle.dispatchEvent(new UIEvent('input'));
+ tick(0);
+ expect(component.value).toBe(-123, 'input -1-2-3');
+ }));
+
+ it('should blur check work', fakeAsync(() => {
component.max = 20;
component.min = 10;
fixture.detectChanges();
inputEle.value = 34;
inputEle.dispatchEvent(new UIEvent('input'));
- expect(component.value).toBe(20, 'set input');
+ tick(0);
+ inputEle.dispatchEvent(new Event('blur'));
+ expect(component.value).toBe(20, 'check max input');
inputEle.value = 4;
inputEle.dispatchEvent(new UIEvent('input'));
- expect(component.value).toBe(10, 'set input');
+ tick(0);
+ inputEle.dispatchEvent(new Event('blur'));
+ expect(component.value).toBe(10, 'check min input');
inputEle.value = 15;
inputEle.dispatchEvent(new UIEvent('input'));
- expect(component.value).toBe(15, 'set input');
-
- component.readOnly = true;
- fixture.detectChanges();
- expect(inputEle.getAttribute('readonly')).not.toBeNull('readonly is null');
+ tick(0);
+ inputEle.dispatchEvent(new Event('blur'));
+ expect(component.value).toBe(15, 'check normal input');
}));
it('should onChange work', () => {
diff --git a/components/stepper/stepper.component.ts b/components/stepper/stepper.component.ts
index e211226e..8d93ecb4 100644
--- a/components/stepper/stepper.component.ts
+++ b/components/stepper/stepper.component.ts
@@ -30,6 +30,7 @@ export class StepperComponent implements OnChanges, ControlValueAccessor {
private _downDisabled: boolean = false;
private _isUpClick: boolean = false;
private _isDownClick: boolean = false;
+ private _inputLock = false;
@Input()
get max(): number {
@@ -141,20 +142,72 @@ export class StepperComponent implements OnChanges, ControlValueAccessor {
}
}
+ compositionStart() {
+ this._inputLock = true;
+ }
+
+ compositionEnd() {
+ this._inputLock = false;
+ }
+
inputChange(event) {
- const value = event;
- this._value = value ? +value : 0;
+ // 'compositionend' is earlier than ngModelChange, Therefore use timer to make ngModelChange runs after 'compositionend' event
+ setTimeout(() => {
+ if (this._inputLock) {
+ return;
+ }
+
+ const allowDecimal = this._step % 1 !== 0;
+ const allowNegative = this._min < 0;
+ let decimalFlag = false;
+ let negativeFlag = false;
+ let value = event.toString().replace(/\D/g, (match, index, str) => {
+ if (allowDecimal && match === '.' && !decimalFlag) {
+ decimalFlag = true;
+ return '.';
+ }
+ if (allowNegative && match === '-' && !negativeFlag) {
+ negativeFlag = true;
+ return '-';
+ }
+ return '';
+ });
+
+ if (negativeFlag && value.indexOf('-') > 0) {
+ value = value.replace(/-/g, '');
+ }
+
+ if (!isNaN(value)) {
+ this._value = +value;
+ this._upDisabled = this.plus(this._value, this._step) > this._max ? true : false;
+ this._downDisabled = this.minus(this._value, this._step) < this._min ? true : false;
+ }
+
+ this.setCls();
+ this.onChange.emit(this._value);
+ this.onChangeFn(this._value);
+ }, 0);
+ }
+
+ inputBlur() {
+ let value = +this._value;
+ if (+this._value === -0) {
+ value = 0;
+ }
if (this._value < this._min) {
- this._value = this._min;
+ value = this._min;
+ } else if (this._value > this._max) {
+ value = this._max;
}
- if (this._value > this._max) {
- this._value = this._max;
+
+ const len = this._step.toString().length - this._step.toString().indexOf('.') - 1;
+ value = +value.toFixed(len);
+
+ if (value !== this._value) {
+ this._value = value;
+ this.onChange.emit(this._value);
+ this.onChangeFn(this._value);
}
- this._upDisabled = this.plus(this._value, this._step) > this._max ? true : false;
- this._downDisabled = this.minus(this._value, this._step) < this._min ? true : false;
- this.setCls();
- this.onChange.emit(this._value);
- this.onChangeFn(this._value);
}
setCls() {