Skip to content

Commit 5c9b975

Browse files
committed
fix(material-experimental/mdc-slider): untangle circular deps
* move dummy MatSlider interfaces from slider-adapter and slider-thumb to slider-interface * create MatSliderThumb and MatSliderDragEvent dummy interfaces to avoid a circular dep between slider-thumb and slider-interface when defining the dummy MatSliderThumb interface * make MatSlider implement the dummy _MatSliderInterface
1 parent 62497a0 commit 5c9b975

File tree

4 files changed

+184
-71
lines changed

4 files changed

+184
-71
lines changed

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

Lines changed: 5 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,15 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {ChangeDetectorRef, ElementRef, Inject} from '@angular/core';
9+
import {Inject} from '@angular/core';
1010
import {SpecificEventListener, EventType} from '@material/base';
1111
import {MDCSliderAdapter, Thumb, TickMark} from '@material/slider';
12-
import {MatSliderThumb, MAT_SLIDER} from './slider-thumb';
13-
14-
/**
15-
* This is a dummy interface that just contains the properties and methods of MatSlider that are
16-
* used by SliderAdapter. Rather than directly referencing MatSlider, we use this interface when
17-
* to avoid a circular dependency between MatSlider and SliderAdapter.
18-
*/
19-
interface MatSlider {
20-
_cdr: ChangeDetectorRef;
21-
min: number;
22-
max: number;
23-
disabled: boolean;
24-
_elementRef: ElementRef<HTMLElement>;
25-
_trackActive: ElementRef<HTMLElement>;
26-
_initialized: boolean;
27-
_tickMarks: TickMark[];
28-
_document: Document;
29-
_window: Window;
30-
displayWith: ((value: number) => string) | null;
31-
_getInput: (thumb: Thumb) => MatSliderThumb;
32-
_getKnobElement: (thumb: Thumb) => HTMLElement;
33-
_getThumbElement: (thumb: Thumb) => HTMLElement;
34-
_getInputElement: (thumb: Thumb) => HTMLInputElement;
35-
_setValue: (value: number, thumb: Thumb) => void;
36-
_setValueIndicatorText: (value: number, thumb: Thumb) => void;
37-
}
12+
import {_MatSliderInterface, MAT_SLIDER} from './slider-interface';
3813

3914
// TODO(wagnermaciel): Change to prototype methods once this PR is submitted.
4015
// https://github.com/material-components/material-components-web/pull/6256
4116
export class SliderAdapter implements MDCSliderAdapter {
42-
constructor(@Inject(MAT_SLIDER) private readonly _delegate: MatSlider) {}
17+
constructor(@Inject(MAT_SLIDER) private readonly _delegate: _MatSliderInterface) {}
4318
hasClass = (className: string): boolean => {
4419
return this._delegate._elementRef.nativeElement.classList.contains(className);
4520
}
@@ -125,21 +100,11 @@ export class SliderAdapter implements MDCSliderAdapter {
125100
emitInputEvent = (value: number, thumb: Thumb): void => {};
126101
emitDragStartEvent = (value: number, thumb: Thumb): void => {
127102
const input = this._delegate._getInput(thumb);
128-
input.dragStart.emit({
129-
source: input,
130-
parent: this._delegate,
131-
value,
132-
thumb,
133-
});
103+
input.dragStart.emit({ source: input, value, thumb });
134104
}
135105
emitDragEndEvent = (value: number, thumb: Thumb): void => {
136106
const input = this._delegate._getInput(thumb);
137-
input.dragEnd.emit({
138-
source: input,
139-
parent: this._delegate,
140-
value,
141-
thumb,
142-
});
107+
input.dragEnd.emit({ source: input, value, thumb });
143108
}
144109
registerEventHandler =
145110
<K extends EventType>(evtType: K, handler: SpecificEventListener<K>): void => {
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {
10+
ChangeDetectorRef,
11+
ElementRef,
12+
EventEmitter,
13+
InjectionToken,
14+
QueryList,
15+
} from '@angular/core';
16+
import {Thumb, TickMark} from '@material/slider';
17+
18+
/**
19+
* Represents a drag event emitted by the MatSlider component.
20+
*/
21+
interface _MatSliderDragEventInterface {
22+
/** The MatSliderThumb that was interacted with. */
23+
source: _MatSliderThumbInterface;
24+
25+
/** The current value of the slider. */
26+
value: number;
27+
28+
/** The thumb that was interacted with. */
29+
thumb: Thumb;
30+
}
31+
32+
export interface _MatSliderThumbInterface {
33+
/** The current value of this slider input. */
34+
value: number;
35+
36+
/** Event emitted when the slider thumb starts being dragged. */
37+
dragStart: EventEmitter<_MatSliderDragEventInterface>;
38+
39+
/** Event emitted when the slider thumb stops being dragged. */
40+
dragEnd: EventEmitter<_MatSliderDragEventInterface>;
41+
42+
/** Event emitted every time the MatSliderThumb is blurred. */
43+
_blur: EventEmitter<void>;
44+
45+
/** Event emitted every time the MatSliderThumb is focused. */
46+
_focus: EventEmitter<void>;
47+
48+
/** Indicates which slider thumb this input corresponds to. */
49+
thumb: Thumb;
50+
51+
/** A reference to MatSliderThumbs root/host element. */
52+
_elementRef: ElementRef<HTMLInputElement>;
53+
54+
/** The injected document if available or fallback to the global document reference. */
55+
_document: Document;
56+
57+
/** Returns true if this slider input currently has focus. */
58+
_isFocused: () => boolean;
59+
}
60+
61+
62+
/**
63+
* This is a dummy interface that just contains the properties and methods of MatSlider that are
64+
* used by MatSliderThumb. Rather than directly referencing MatSlider, we use this interface when
65+
* defining MAT_SLIDER to avoid a circular dependency between MatSlider and MatSliderThumb.
66+
*/
67+
export interface _MatSliderInterface {
68+
/** The slider thumb(s). */
69+
_thumbs: QueryList<ElementRef<HTMLElement>>;
70+
71+
/** The slider thumb knob(s) */
72+
_knobs: QueryList<ElementRef<HTMLElement>>;
73+
74+
/** The span containing the slider thumb value indicator text */
75+
_valueIndicatorTextElements: QueryList<ElementRef<HTMLElement>>;
76+
77+
/** The active section of the slider track. */
78+
_trackActive: ElementRef<HTMLElement>;
79+
80+
/** The sliders hidden range input(s). */
81+
_inputs: QueryList<_MatSliderThumbInterface>;
82+
83+
/** Whether the slider is disabled. */
84+
disabled: boolean;
85+
86+
/** Whether the slider displays a numeric value label upon pressing the thumb. */
87+
discrete: boolean;
88+
89+
/** Whether the slider displays tick marks along the slider track. */
90+
showTickMarks: boolean;
91+
92+
/** The minimum value that the slider can have. */
93+
min: number;
94+
95+
/** The maximum value that the slider can have. */
96+
max: number;
97+
98+
/** The values at which the thumb will snap. */
99+
step: number;
100+
101+
/**
102+
* Function that will be used to format the value before it is displayed
103+
* in the thumb label. Can be used to format very large number in order
104+
* for them to fit into the slider thumb.
105+
*/
106+
displayWith: ((value: number) => string) | null;
107+
108+
/** Whether the foundation has been initialized. */
109+
_initialized: boolean;
110+
111+
/** The injected document if available or fallback to the global document reference. */
112+
_document: Document;
113+
114+
/**
115+
* The defaultView of the injected document if
116+
* available or fallback to global window reference.
117+
*/
118+
_window: Window;
119+
120+
/** Used to keep track of & render the active & inactive tick marks on the slider track. */
121+
_tickMarks: TickMark[];
122+
123+
/** The change detector ref. */
124+
_cdr: ChangeDetectorRef;
125+
126+
/** A reference to MatSliders root/host element. */
127+
_elementRef: ElementRef<HTMLElement>;
128+
129+
/** Sets the value of a slider thumb. */
130+
_setValue: (value: number, thumb: Thumb) => void;
131+
132+
/** Whether this is a ranged slider. */
133+
_isRange: () => boolean;
134+
135+
/** Gets the slider thumb input of the given thumb. */
136+
_getInput: (thumb: Thumb) => _MatSliderThumbInterface;
137+
138+
/** Gets the slider thumb HTML input element of the given thumb. */
139+
_getInputElement: (thumb: Thumb) => HTMLInputElement;
140+
141+
/** Gets the slider thumb HTML element of the given thumb. */
142+
_getThumbElement: (thumb: Thumb) => HTMLElement;
143+
144+
/** Gets the slider knob HTML element of the given thumb. */
145+
_getKnobElement: (thumb: Thumb) => HTMLElement;
146+
147+
/**
148+
* Sets the value indicator text of the given thumb using the given value.
149+
*
150+
* Uses the `displayWith` function if one has been provided. Otherwise, it just uses the
151+
* numeric value as a string.
152+
*/
153+
_setValueIndicatorText: (value: number, thumb: Thumb) => void;
154+
155+
/** Determines the class name for a HTML element. */
156+
_getTickMarkClass: (tickMark: TickMark) => string;
157+
158+
/** Returns an array of the thumb types that exist on the current slider instance. */
159+
_getThumbTypes: () => Thumb[];
160+
}
161+
162+
/**
163+
* Injection token that can be used to inject instances of MatSlider.
164+
*/
165+
export const MAT_SLIDER = new InjectionToken<_MatSliderInterface>('MatSlider');

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

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,11 @@ import {
1414
ElementRef,
1515
EventEmitter,
1616
Inject,
17-
InjectionToken,
1817
Input,
1918
Output,
2019
} from '@angular/core';
2120
import {Thumb} from '@material/slider';
22-
23-
/**
24-
* This is a dummy interface that just contains the properties and methods of MatSlider that are
25-
* used by MatSliderThumb. Rather than directly referencing MatSlider, we use this interface when
26-
* defining MAT_SLIDER to avoid a circular dependency between MatSlider and MatSliderThumb.
27-
*/
28-
interface MatSlider {
29-
min: number;
30-
max: number;
31-
disabled: boolean;
32-
_initialized: boolean;
33-
_getInput: (thumb: Thumb) => MatSliderThumb;
34-
_setValue: (value: number, thumb: Thumb) => void;
35-
}
36-
37-
/**
38-
* Injection token that can be used to inject instances of MatSlider.
39-
*/
40-
export const MAT_SLIDER = new InjectionToken<MatSlider>('MatSlider');
21+
import {_MatSliderInterface, MAT_SLIDER} from './slider-interface';
4122

4223
/**
4324
* Represents a drag event emitted by the MatSlider component.
@@ -46,9 +27,6 @@ export interface MatSliderDragEvent {
4627
/** The MatSliderThumb that was interacted with. */
4728
source: MatSliderThumb;
4829

49-
/** The parent MatSlider that was interacted with. */
50-
parent: MatSlider;
51-
5230
/** The current value of the slider. */
5331
value: number;
5432

@@ -116,11 +94,14 @@ export class MatSliderThumb implements AfterViewInit {
11694
/** Indicates which slider thumb this input corresponds to. */
11795
thumb: Thumb;
11896

97+
private _document: Document;
98+
11999
constructor(
120-
@Inject(DOCUMENT) private readonly _document: Document,
121-
@Inject(MAT_SLIDER) private readonly _slider: MatSlider,
100+
@Inject(DOCUMENT) document: any,
101+
@Inject(MAT_SLIDER) private readonly _slider: _MatSliderInterface,
122102
readonly _elementRef: ElementRef<HTMLInputElement>,
123103
) {
104+
this._document = document;
124105
this.thumb = _elementRef.nativeElement.hasAttribute('matSliderStartThumb')
125106
? Thumb.START
126107
: Thumb.END;

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ import {
3131
} from '@angular/core';
3232
import {MDCSliderFoundation, Thumb, TickMark} from '@material/slider';
3333
import {SliderAdapter} from './slider-adapter';
34-
import {MatSliderThumb, MAT_SLIDER} from './slider-thumb';
34+
import {MatSliderThumb} from './slider-thumb';
35+
import {_MatSliderInterface, _MatSliderThumbInterface, MAT_SLIDER} from './slider-interface';
3536

3637
/**
3738
* Allows users to select from a range of values by moving the slider thumb. It is similar in
@@ -53,7 +54,7 @@ import {MatSliderThumb, MAT_SLIDER} from './slider-thumb';
5354
encapsulation: ViewEncapsulation.None,
5455
providers: [{provide: MAT_SLIDER, useExisting: MatSlider}],
5556
})
56-
export class MatSlider implements AfterViewInit, OnDestroy {
57+
export class MatSlider implements _MatSliderInterface, AfterViewInit, OnDestroy {
5758
/** The slider thumb(s). */
5859
@ViewChildren('thumb') _thumbs: QueryList<ElementRef<HTMLElement>>;
5960

@@ -68,7 +69,8 @@ export class MatSlider implements AfterViewInit, OnDestroy {
6869
@ViewChild('trackActive') _trackActive: ElementRef<HTMLElement>;
6970

7071
/** The sliders hidden range input(s). */
71-
@ContentChildren(MatSliderThumb, {descendants: false}) _inputs: QueryList<MatSliderThumb>;
72+
@ContentChildren(MatSliderThumb, {descendants: false})
73+
_inputs: QueryList<_MatSliderThumbInterface>;
7274

7375
/** Whether the slider is disabled. */
7476
@Input()
@@ -101,13 +103,13 @@ export class MatSlider implements AfterViewInit, OnDestroy {
101103
@Input()
102104
get min(): number { return this._min; }
103105
set min(v: number) { this._min = coerceNumberProperty(v, this._min); }
104-
private _min = 0;
106+
private _min: number = 0;
105107

106108
/** The maximum value that the slider can have. */
107109
@Input()
108110
get max(): number { return this._max; }
109111
set max(v: number) { this._max = coerceNumberProperty(v, this._max); }
110-
private _max = 100;
112+
private _max: number = 100;
111113

112114
/** The values at which the thumb will snap. */
113115
@Input()
@@ -183,7 +185,7 @@ export class MatSlider implements AfterViewInit, OnDestroy {
183185
}
184186

185187
/** Gets the slider thumb input of the given thumb. */
186-
_getInput(thumb: Thumb): MatSliderThumb {
188+
_getInput(thumb: Thumb): _MatSliderThumbInterface {
187189
return thumb === Thumb.END ? this._inputs.last! : this._inputs.first!;
188190
}
189191

0 commit comments

Comments
 (0)