From 7f50d11d9573d8b8682effe3425d043ec9359af0 Mon Sep 17 00:00:00 2001 From: mmalerba Date: Thu, 2 Feb 2017 13:47:01 -0800 Subject: [PATCH] fix(slider): fire change event on value change via keyboard. (#2807) --- src/lib/slider/slider.spec.ts | 70 +++++++++++++++++++++++++++++++---- src/lib/slider/slider.ts | 8 ++++ 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/src/lib/slider/slider.spec.ts b/src/lib/slider/slider.spec.ts index 18017694679..99672f76eea 100644 --- a/src/lib/slider/slider.spec.ts +++ b/src/lib/slider/slider.spec.ts @@ -1,5 +1,5 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing'; -import {ReactiveFormsModule, FormControl} from '@angular/forms'; +import {ReactiveFormsModule, FormControl, FormsModule} from '@angular/forms'; import {Component, DebugElement} from '@angular/core'; import {By, HAMMER_GESTURE_CONFIG} from '@angular/platform-browser'; import {MdSlider, MdSliderModule} from './slider'; @@ -22,7 +22,7 @@ describe('MdSlider', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [MdSliderModule.forRoot(), RtlModule.forRoot(), ReactiveFormsModule], + imports: [MdSliderModule.forRoot(), RtlModule.forRoot(), ReactiveFormsModule, FormsModule], declarations: [ StandardSlider, DisabledSlider, @@ -33,7 +33,8 @@ describe('MdSlider', () => { SliderWithSetTickInterval, SliderWithThumbLabel, SliderWithOneWayBinding, - SliderWithTwoWayBinding, + SliderWithFormControl, + SliderWithNgModel, SliderWithValueSmallerThanMin, SliderWithValueGreaterThanMax, SliderWithChangeHandler, @@ -585,15 +586,15 @@ describe('MdSlider', () => { }); describe('slider as a custom form control', () => { - let fixture: ComponentFixture; + let fixture: ComponentFixture; let sliderDebugElement: DebugElement; let sliderNativeElement: HTMLElement; let sliderInstance: MdSlider; let sliderWrapperElement: HTMLElement; - let testComponent: SliderWithTwoWayBinding; + let testComponent: SliderWithFormControl; beforeEach(() => { - fixture = TestBed.createComponent(SliderWithTwoWayBinding); + fixture = TestBed.createComponent(SliderWithFormControl); fixture.detectChanges(); testComponent = fixture.debugElement.componentInstance; @@ -684,7 +685,54 @@ describe('MdSlider', () => { expect(sliderControl.pristine).toBe(false); expect(sliderControl.touched).toBe(true); }); + }); + describe('slider with ngModel', () => { + let fixture: ComponentFixture; + let sliderDebugElement: DebugElement; + let sliderNativeElement: HTMLElement; + let sliderInstance: MdSlider; + let sliderWrapperElement: HTMLElement; + let testComponent: SliderWithNgModel; + + beforeEach(() => { + fixture = TestBed.createComponent(SliderWithNgModel); + fixture.detectChanges(); + + testComponent = fixture.debugElement.componentInstance; + + sliderDebugElement = fixture.debugElement.query(By.directive(MdSlider)); + sliderNativeElement = sliderDebugElement.nativeElement; + sliderInstance = sliderDebugElement.injector.get(MdSlider); + sliderWrapperElement = sliderNativeElement.querySelector('.md-slider-wrapper'); + }); + + it('should update the model on click', () => { + expect(testComponent.val).toBe(0); + + dispatchClickEventSequence(sliderNativeElement, 0.76); + fixture.detectChanges(); + + expect(testComponent.val).toBe(76); + }); + + it('should update the model on slide', () => { + expect(testComponent.val).toBe(0); + + dispatchSlideEventSequence(sliderNativeElement, 0, 0.19, gestureConfig); + fixture.detectChanges(); + + expect(testComponent.val).toBe(19); + }); + + it('should update the model on keydown', () => { + expect(testComponent.val).toBe(0); + + dispatchKeydownEvent(sliderNativeElement, UP_ARROW); + fixture.detectChanges(); + + expect(testComponent.val).toBe(1); + }); }); describe('slider with value property binding', () => { @@ -1222,10 +1270,18 @@ class SliderWithOneWayBinding { template: ``, styles: [styles], }) -class SliderWithTwoWayBinding { +class SliderWithFormControl { control = new FormControl(0); } +@Component({ + template: ``, + styles: [styles], +}) +class SliderWithNgModel { + val = 0; +} + @Component({ template: ``, styles: [styles], diff --git a/src/lib/slider/slider.ts b/src/lib/slider/slider.ts index fac9b9382b8..5fa5a163607 100644 --- a/src/lib/slider/slider.ts +++ b/src/lib/slider/slider.ts @@ -75,6 +75,7 @@ export class MdSliderChange { '(blur)': '_onBlur()', '(click)': '_onClick($event)', '(keydown)': '_onKeydown($event)', + '(keyup)': '_onKeyup()', '(mouseenter)': '_onMouseenter()', '(slide)': '_onSlide($event)', '(slideend)': '_onSlideEnd()', @@ -485,12 +486,19 @@ export class MdSlider implements ControlValueAccessor { return; } + this._isSliding = true; event.preventDefault(); } + _onKeyup() { + this._isSliding = false; + } + /** Increments the slider by the given number of steps (negative number decrements). */ private _increment(numSteps: number) { this.value = this._clamp(this.value + this.step * numSteps, this.min, this.max); + this._emitInputEvent(); + this._emitValueIfChanged(); } /** Calculate the new value from the new physical location. The value will always be snapped. */