Skip to content

Commit

Permalink
feat(module: range): range add ngmodel (#208)
Browse files Browse the repository at this point in the history
  • Loading branch information
sWhite01111 authored and fisherspy committed Dec 29, 2018
1 parent c1e6d11 commit 26d019d
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 95 deletions.
87 changes: 50 additions & 37 deletions components/range/demo/basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,54 @@ import { Component } from '@angular/core';
<div class="am-demo-page">
<div style="padding: 15px;font-size: 16px;">步骤条</div>
<div class="am-demo-bd am-wingblank am-wingblank-lg">
<div>
<div class="sub-title">Basic range</div>
</div>
<div>
<Range [defaultValue]=[3,10]
[min]=0
[max]=20
(onChange)="change($event)"
(onAfterChange)="afterChange($event)"
></Range>
</div>
<div><div class="sub-title">Basic range ngModel</div></div>
<div>
<Range [ngModel]="valueModel"
[min]="0"
[max]="20"
(ngModelChange)="changeModel($event)">
</Range>
</div>
</div>
<div class="am-demo-bd am-wingblank am-wingblank-lg">
<div><div class="sub-title">Basic range</div></div>
<div>
<Range
[defaultValue]="[3, 10]"
[min]="0"
[max]="20"
(onChange)="change($event)"
(onAfterChange)="afterChange($event)"
></Range>
</div>
</div>
<div class="am-demo-bd am-wingblank am-wingblank-lg">
<div>
<div class="sub-title">Disabled range</div>
</div>
<div>
<Range [defaultValue]=[3,10]
[min]=0
[max]=20
[disabled]=true
(onChange)="change($event)"
(onAfterChange)="afterChange($event)"
></Range>
</div>
<div><div class="sub-title">Disabled range</div></div>
<div>
<Range
[defaultValue]="[3, 10]"
[min]="0"
[max]="20"
[disabled]="true"
(onChange)="change($event)"
(onAfterChange)="afterChange($event)"
></Range>
</div>
</div>
<div class="am-demo-bd am-wingblank am-wingblank-lg">
<div>
<div class="sub-title">Range with customized style</div>
</div>
<div>
<Range [defaultValue]=[3,10]
[min]=0
[max]=20
[trackStyle]="trackStyle"
[railStyle]="railStyle"
[handleStyle]="handleStyle"
(onChange)="change($event)"
(onAfterChange)="afterChange($event)"
></Range>
</div>
<div><div class="sub-title">Range with customized style</div></div>
<div>
<Range
[defaultValue]="[3, 10]"
[min]="0"
[max]="20"
[trackStyle]="trackStyle"
[railStyle]="railStyle"
[handleStyle]="handleStyle"
(onChange)="change($event)"
(onAfterChange)="afterChange($event)"
></Range>
</div>
</div>
</div>
`,
Expand All @@ -69,6 +76,7 @@ import { Component } from '@angular/core';
})
export class DemoRangeBasicComponent {
value = [20, 50];
valueModel = [4, 8];
trackStyle = [{ 'background-color': 'red' }, { 'background-color': 'green' }];
railStyle = {
'background-color': 'black'
Expand All @@ -84,4 +92,9 @@ export class DemoRangeBasicComponent {
afterChange(e) {
console.log(e, 'afterChange');
}

changeModel(e) {
console.log(e, 'changeModel');
console.log(this.valueModel, 'valueModel');
}
}
2 changes: 2 additions & 0 deletions components/range/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ A `Range` component for selecting particular value in range, eg: controls the di

Properties | Descrition | Type | Default
-----------|------------|------|--------
| ngModel| Number | | The value of slider, double binding. |
| ngModelChange | Function | Noop | Callback function that is called when the user changes the slider's value. |
| min | Number | 0 | The minimum value the slider can slide to. |
| max | Number | 100 | The maximum value the slider can slide to. |
| step | Number or null | 1 | The granularity the slider can step through values. Must greater than 0, and be divided by (max - min) . When `marks` no null, `step` can be `null`. |
Expand Down
4 changes: 3 additions & 1 deletion components/range/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ subtitle: 区域选择

属性 | 类型 | 默认值 | 说明
----|-----|------|------
| ngModel| Number | | 设置当前取值,可双向绑定。 |
| ngModelChange | Function | Noop | 当 Slider 的值发生改变时,会触发 ngModelChange 事件,并把改变后的值作为参数传入。 |
| min | Number | 0 | 最小值 |
| max | Number | 100 | 最大值 |
| step | Number or null | 1 | 步长,取值必须大于 0,并且可被 (max - min) 整除。当 `marks` 不为空对象时,可以设置 `step``null`,此时 Slider 的可选值仅有 marks 标出来的部分。 |
Expand All @@ -29,7 +31,7 @@ subtitle: 区域选择
| marks | Object{Number:String} | { } | 刻度标记,key 的类型必须为 `Number` 且取值在闭区间 [min, max]|
| count | number | `1` | Determine how many ranges to render, and multiple handles will be rendered (number + 1). |
| allowCross | boolean | `true` | `allowCross` could be set as `true` to allow those handles to cross. |
| pushable | number | `true` | minimum ensured distance between handles |
| pushable | number | | minimum ensured distance between handles |
| handleStyle | Array[Object] | - | 滑块的样式,按数组顺序应用到多滑块 |
| trackStyle | Array[Object] | - | 选中部分滑动条的样式,按数组顺序应用到滑动条的多区间 |
| railStyle | Object | - | 未选中部分 |
133 changes: 105 additions & 28 deletions components/range/range.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { async, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { RangeModule } from './range.module';
import { dispatchMouseEvent } from '../core/testing';
import { dispatchMouseEvent, dispatchTouchEvent } from '../core/testing';

describe('RangeComponent', () => {
let component: TestRangeComponent;
Expand All @@ -14,7 +15,7 @@ describe('RangeComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TestRangeComponent],
imports: [RangeModule]
imports: [RangeModule, FormsModule]
}).compileComponents();
}));

Expand All @@ -27,11 +28,11 @@ describe('RangeComponent', () => {
sliderHandler = rangeEle.nativeElement.querySelectorAll('.am-slider-handle');
fixture.detectChanges();
});

it('should verifyPushable work', () => {
component.value = [30, 40];
component.pushable = 15;
fixture.detectChanges();
component.value = [30, 40];
fixture.detectChanges();
expect(sliderHandler[0].getAttribute('style')).toContain('left: 20%');
});

Expand All @@ -41,15 +42,21 @@ describe('RangeComponent', () => {
expect(sliderHandler[1].getAttribute('style')).toContain('left: 50%');
});
it('should value work', () => {
component.value = [30, 60];
component.value = [30, 120];
fixture.detectChanges();
sliderHandler = rangeEle.nativeElement.querySelectorAll('.am-slider-handle');
expect(sliderHandler[0].getAttribute('style')).toContain('left: 30%');
expect(sliderHandler[1].getAttribute('style')).toContain('left: 100%');

component.value = [-30, 60];
fixture.detectChanges();
sliderHandler = rangeEle.nativeElement.querySelectorAll('.am-slider-handle');
expect(sliderHandler[0].getAttribute('style')).toContain('left: 0%');
expect(sliderHandler[1].getAttribute('style')).toContain('left: 60%');
});
it('should allowCross=true work', () => {
component.allowCross = true;
fixture.detectChanges();
// component.allowCross = true;
// fixture.detectChanges();

const sliderHandlerNodeList = rangeEle.nativeElement.querySelectorAll('sliderhandle');
dispatchMouseEvent(sliderHandlerNodeList[0], 'mousedown');
Expand Down Expand Up @@ -107,29 +114,68 @@ describe('RangeComponent', () => {
expect(sliderHandler[0].getAttribute('style')).toContain('left: ' + offset + '%');
});
});
describe('RangeModelComponent', () => {
let component: TestRangeModelComponent;
let fixture: ComponentFixture<TestRangeModelComponent>;
let rangeEle;
let amSlider;
let sliderHandler;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TestRangeModelComponent],
imports: [RangeModule, FormsModule]
}).compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(TestRangeModelComponent);
component = fixture.componentInstance;
rangeEle = fixture.debugElement.query(By.css('Range'));
fixture.detectChanges();
amSlider = rangeEle.nativeElement.querySelector('.am-slider');
sliderHandler = rangeEle.nativeElement.querySelectorAll('.am-slider-handle');
fixture.detectChanges();
});
it('should ngModel work', fakeAsync(() => {
const sliderHandlerNodeList = rangeEle.nativeElement.querySelectorAll('sliderhandle');
dispatchMouseEvent(sliderHandlerNodeList[1], 'mousedown');
fixture.detectChanges();
dispatchMouseEvent(document, 'mousemove', 600);
fixture.detectChanges();
dispatchMouseEvent(document, 'mouseup');
fixture.detectChanges();
tick();
sliderHandler = rangeEle.nativeElement.querySelectorAll('.am-slider-handle');
expect(sliderHandler[1].getAttribute('style')).toContain('left: ' + 0 + '%');
expect(component.valueModel).toEqual([0, 20]);
expect(component.changeModel).toHaveBeenCalled();
}));
});

@Component({
selector: 'test-range',
template: `
<Range [max]="max"
[min]= "min"
[dots]="dots"
[step]="step"
[value]="value"
[marks]="marks"
[count]="count"
[disabled]="disabled"
[included]="included"
[pushable]="pushable"
[railStyle]="railStyle"
[allowCross]="allowCross"
[trackStyle]="trackStyle"
[handleStyle]="handleStyle"
[defaultValue]="defaultValue"
(onChange)="change($event)"
(onAfterChange)="afterChange($event)"
></Range>
`
<Range
[max]="max"
[min]="min"
[dots]="dots"
[step]="step"
[value]="value"
[marks]="marks"
[count]="count"
[disabled]="disabled"
[included]="included"
[pushable]="pushable"
[railStyle]="railStyle"
[allowCross]="allowCross"
[trackStyle]="trackStyle"
[handleStyle]="handleStyle"
[defaultValue]="defaultValue"
(onChange)="change($event)"
(onAfterChange)="afterChange($event)"
></Range>
`
})
export class TestRangeComponent {
min = 0;
Expand All @@ -141,8 +187,9 @@ export class TestRangeComponent {
dots = false;
included = true;
value;
valueModel = [20, 80];
count = 1;
allowCross;
allowCross = true;
pushable;
trackStyle = [{ 'background-color': 'red' }, { 'background-color': 'green' }];
railStyle = {
Expand All @@ -152,6 +199,36 @@ export class TestRangeComponent {

afterChange = jasmine.createSpy('afterChange callback');
change = jasmine.createSpy('change callback');
changeModel = jasmine.createSpy('changeModel callback');

constructor() {}
}

@Component({
selector: 'test-range-model',
template: `
<Range
[max]="max"
[min]="min"
[(ngModel)]="valueModel"
[defaultValue]="defaultValue"
(onChange)="change($event)"
(onAfterChange)="afterChange($event)"
(ngModelChange)="changeModel($event)"
></Range>
`
})
export class TestRangeModelComponent {
min = 0;
max = 100;
valueModel = [20, 80];
defaultValue = [20, 80];
count = 1;
allowCross = true;

afterChange = jasmine.createSpy('afterChange callback');
change = jasmine.createSpy('change callback');
changeModel = jasmine.createSpy('changeModel callback');

constructor() {}
}
Loading

0 comments on commit 26d019d

Please sign in to comment.