Skip to content

Commit 0ee0692

Browse files
committed
feat(material-experimental/mdc-slider): implement control value accessor (#22016)
* feat(material-experimental/mdc-slider): implement control value accessor
1 parent ef54d5e commit 0ee0692

File tree

1 file changed

+71
-3
lines changed
  • src/material-experimental/mdc-slider

1 file changed

+71
-3
lines changed

src/material-experimental/mdc-slider/slider.ts

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
ViewChildren,
3434
ViewEncapsulation,
3535
} from '@angular/core';
36+
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
3637
import {
3738
CanColorCtor,
3839
MatRipple,
@@ -249,11 +250,16 @@ export class MatSliderVisualThumb implements AfterViewInit, OnDestroy {
249250
host: {
250251
'class': 'mdc-slider__input',
251252
'type': 'range',
252-
'(blur)': '_blur.emit()',
253+
'(blur)': '_onBlur()',
253254
'(focus)': '_focus.emit()',
254255
},
256+
providers: [{
257+
provide: NG_VALUE_ACCESSOR,
258+
useExisting: MatSliderThumb,
259+
multi: true
260+
}],
255261
})
256-
export class MatSliderThumb implements AfterViewInit {
262+
export class MatSliderThumb implements AfterViewInit, ControlValueAccessor {
257263

258264
// ** IMPORTANT NOTE **
259265
//
@@ -298,6 +304,20 @@ export class MatSliderThumb implements AfterViewInit {
298304
/** Event emitted every time the MatSliderThumb is focused. */
299305
@Output() readonly _focus: EventEmitter<void> = new EventEmitter<void>();
300306

307+
_disabled: boolean = false;
308+
309+
/**
310+
* A callback function that is called when the
311+
* control's value changes in the UI (ControlValueAccessor).
312+
*/
313+
_onChange: (value: any) => void = () => {};
314+
315+
/**
316+
* A callback function that is called by the forms API on
317+
* initialization to update the form model on blur (ControlValueAccessor).
318+
*/
319+
private _onTouched: () => void = () => {};
320+
301321
/** Indicates which slider thumb this input corresponds to. */
302322
_thumbPosition: Thumb = this._elementRef.nativeElement.hasAttribute('matSliderStartThumb')
303323
? Thumb.START
@@ -331,6 +351,47 @@ export class MatSliderThumb implements AfterViewInit {
331351
}
332352
}
333353

354+
_onBlur(): void {
355+
this._onTouched();
356+
this._blur.emit();
357+
}
358+
359+
/**
360+
* Sets the model value. Implemented as part of ControlValueAccessor.
361+
* @param value
362+
*/
363+
writeValue(value: any): void {
364+
this.value = value;
365+
}
366+
367+
/**
368+
* Registers a callback to be triggered when the value has changed.
369+
* Implemented as part of ControlValueAccessor.
370+
* @param fn Callback to be registered.
371+
*/
372+
registerOnChange(fn: any): void {
373+
this._onChange = fn;
374+
}
375+
376+
/**
377+
* Registers a callback to be triggered when the component is touched.
378+
* Implemented as part of ControlValueAccessor.
379+
* @param fn Callback to be registered.
380+
*/
381+
registerOnTouched(fn: any): void {
382+
this._onTouched = fn;
383+
}
384+
385+
/**
386+
* Sets whether the component should be disabled.
387+
* Implemented as part of ControlValueAccessor.
388+
* @param isDisabled
389+
*/
390+
setDisabledState(isDisabled: boolean): void {
391+
this._disabled = isDisabled;
392+
this._slider._updateDisabled();
393+
}
394+
334395
/** Returns true if this slider input currently has focus. */
335396
_isFocused(): boolean {
336397
return this._document.activeElement === this._hostElement;
@@ -562,6 +623,11 @@ export class MatSlider extends _MatSliderMixinBase implements AfterViewInit, OnD
562623
return this._inputs.length === 2;
563624
}
564625

626+
/** Sets the disabled state based on the disabled state of the inputs (ControlValueAccessor). */
627+
_updateDisabled(): void {
628+
this.disabled = this._inputs.some(input => input._disabled);
629+
}
630+
565631
/** Gets the slider thumb input of the given thumb position. */
566632
_getInput(thumbPosition: Thumb): MatSliderThumb {
567633
return thumbPosition === Thumb.END ? this._inputs.last : this._inputs.first;
@@ -709,7 +775,9 @@ class SliderAdapter implements MDCSliderAdapter {
709775
}
710776
// We ignore emitChangeEvent and emitInputEvent because the slider inputs
711777
// are already exposed so users can just listen for those events directly themselves.
712-
emitChangeEvent = (value: number, thumbPosition: Thumb): void => {};
778+
emitChangeEvent = (value: number, thumbPosition: Thumb): void => {
779+
this._delegate._getInput(thumbPosition)._onChange(value);
780+
}
713781
emitInputEvent = (value: number, thumbPosition: Thumb): void => {};
714782
emitDragStartEvent = (value: number, thumbPosition: Thumb): void => {
715783
const input = this._delegate._getInput(thumbPosition);

0 commit comments

Comments
 (0)