diff --git a/src/material-experimental/mdc-slider/slider.ts b/src/material-experimental/mdc-slider/slider.ts index 59f4f91aa527..4d3c96343a08 100644 --- a/src/material-experimental/mdc-slider/slider.ts +++ b/src/material-experimental/mdc-slider/slider.ts @@ -33,6 +33,7 @@ import { ViewChildren, ViewEncapsulation, } from '@angular/core'; +import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms'; import { CanColorCtor, MatRipple, @@ -249,11 +250,16 @@ export class MatSliderVisualThumb implements AfterViewInit, OnDestroy { host: { 'class': 'mdc-slider__input', 'type': 'range', - '(blur)': '_blur.emit()', + '(blur)': '_onBlur()', '(focus)': '_focus.emit()', }, + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: MatSliderThumb, + multi: true + }], }) -export class MatSliderThumb implements AfterViewInit { +export class MatSliderThumb implements AfterViewInit, ControlValueAccessor { // ** IMPORTANT NOTE ** // @@ -298,6 +304,20 @@ export class MatSliderThumb implements AfterViewInit { /** Event emitted every time the MatSliderThumb is focused. */ @Output() readonly _focus: EventEmitter = new EventEmitter(); + _disabled: boolean = false; + + /** + * A callback function that is called when the + * control's value changes in the UI (ControlValueAccessor). + */ + _onChange: (value: any) => void = () => {}; + + /** + * A callback function that is called by the forms API on + * initialization to update the form model on blur (ControlValueAccessor). + */ + private _onTouched: () => void = () => {}; + /** Indicates which slider thumb this input corresponds to. */ _thumbPosition: Thumb = this._elementRef.nativeElement.hasAttribute('matSliderStartThumb') ? Thumb.START @@ -331,6 +351,47 @@ export class MatSliderThumb implements AfterViewInit { } } + _onBlur(): void { + this._onTouched(); + this._blur.emit(); + } + + /** + * Sets the model value. Implemented as part of ControlValueAccessor. + * @param value + */ + writeValue(value: any): void { + this.value = value; + } + + /** + * Registers a callback to be triggered when the value has changed. + * Implemented as part of ControlValueAccessor. + * @param fn Callback to be registered. + */ + registerOnChange(fn: any): void { + this._onChange = fn; + } + + /** + * Registers a callback to be triggered when the component is touched. + * Implemented as part of ControlValueAccessor. + * @param fn Callback to be registered. + */ + registerOnTouched(fn: any): void { + this._onTouched = fn; + } + + /** + * Sets whether the component should be disabled. + * Implemented as part of ControlValueAccessor. + * @param isDisabled + */ + setDisabledState(isDisabled: boolean): void { + this._disabled = isDisabled; + this._slider._updateDisabled(); + } + /** Returns true if this slider input currently has focus. */ _isFocused(): boolean { return this._document.activeElement === this._hostElement; @@ -562,6 +623,11 @@ export class MatSlider extends _MatSliderMixinBase implements AfterViewInit, OnD return this._inputs.length === 2; } + /** Sets the disabled state based on the disabled state of the inputs (ControlValueAccessor). */ + _updateDisabled(): void { + this.disabled = this._inputs.some(input => input._disabled); + } + /** Gets the slider thumb input of the given thumb position. */ _getInput(thumbPosition: Thumb): MatSliderThumb { return thumbPosition === Thumb.END ? this._inputs.last : this._inputs.first; @@ -709,7 +775,9 @@ class SliderAdapter implements MDCSliderAdapter { } // We ignore emitChangeEvent and emitInputEvent because the slider inputs // are already exposed so users can just listen for those events directly themselves. - emitChangeEvent = (value: number, thumbPosition: Thumb): void => {}; + emitChangeEvent = (value: number, thumbPosition: Thumb): void => { + this._delegate._getInput(thumbPosition)._onChange(value); + } emitInputEvent = (value: number, thumbPosition: Thumb): void => {}; emitDragStartEvent = (value: number, thumbPosition: Thumb): void => { const input = this._delegate._getInput(thumbPosition);