Skip to content

Commit b6712f8

Browse files
crisbetojosephperrott
authored andcommitted
fix(progress-spinner): coerceNumber values (#7791)
Coerces any string values that are passed to `value`, `diameter` and `strokeWidth` to numbers.
1 parent 4b59ca1 commit b6712f8

File tree

2 files changed

+51
-21
lines changed

2 files changed

+51
-21
lines changed

src/lib/progress-spinner/progress-spinner.spec.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ describe('MatProgressSpinner', () => {
1717
ProgressSpinnerCustomStrokeWidth,
1818
ProgressSpinnerCustomDiameter,
1919
SpinnerWithColor,
20+
ProgressSpinnerWithStringValues,
2021
],
2122
}).compileComponents();
2223
}));
@@ -184,6 +185,24 @@ describe('MatProgressSpinner', () => {
184185
expect(fixture.nativeElement.querySelector('svg').getAttribute('focusable')).toBe('false');
185186
});
186187

188+
it('should handle the number inputs being passed in as strings', () => {
189+
const fixture = TestBed.createComponent(ProgressSpinnerWithStringValues);
190+
const spinner = fixture.debugElement.query(By.directive(MatProgressSpinner));
191+
const svgElement = spinner.nativeElement.querySelector('svg');
192+
193+
fixture.detectChanges();
194+
195+
expect(spinner.componentInstance.diameter).toBe(37);
196+
expect(spinner.componentInstance.strokeWidth).toBe(11);
197+
expect(spinner.componentInstance.value).toBe(25);
198+
199+
expect(spinner.nativeElement.style.width).toBe('38px');
200+
expect(spinner.nativeElement.style.height).toBe('38px');
201+
expect(svgElement.style.width).toBe('38px');
202+
expect(svgElement.style.height).toBe('38px');
203+
expect(svgElement.getAttribute('viewBox')).toBe('0 0 38 38');
204+
});
205+
187206
});
188207

189208

@@ -211,3 +230,10 @@ class SpinnerWithColor { color: string = 'primary'; }
211230

212231
@Component({template: `<mat-progress-spinner value="50" [color]="color"></mat-progress-spinner>`})
213232
class ProgressSpinnerWithColor { color: string = 'primary'; }
233+
234+
@Component({
235+
template: `
236+
<mat-progress-spinner value="25" diameter="37" strokeWidth="11"></mat-progress-spinner>
237+
`
238+
})
239+
class ProgressSpinnerWithStringValues { }

src/lib/progress-spinner/progress-spinner.ts

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ import {coerceNumberProperty} from '@angular/cdk/coercion';
2626
/** Possible mode for a progress spinner. */
2727
export type ProgressSpinnerMode = 'determinate' | 'indeterminate';
2828

29+
/**
30+
* Base reference size of the spinner.
31+
* @docs-private
32+
*/
33+
const BASE_SIZE = 100;
34+
35+
/**
36+
* Base reference stroke width of the spinner.
37+
* @docs-private
38+
*/
39+
const BASE_STROKE_WIDTH = 10;
40+
2941
// Boilerplate for applying mixins to MatProgressSpinner.
3042
/** @docs-private */
3143
export class MatProgressSpinnerBase {
@@ -84,17 +96,15 @@ const INDETERMINATE_ANIMATION_TEMPLATE = `
8496
export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements CanColor,
8597
OnChanges {
8698

87-
private _value: number = 0;
88-
private readonly _baseSize = 100;
89-
private readonly _baseStrokeWidth = 10;
90-
private _fallbackAnimation = false;
99+
private _value = 0;
91100
private _strokeWidth: number;
101+
private _fallbackAnimation = false;
92102

93103
/** The width and height of the host element. Will grow with stroke width. **/
94-
_elementSize = this._baseSize;
104+
_elementSize = BASE_SIZE;
95105

96106
/** Tracks diameters of existing instances to de-dupe generated styles (default d = 100) */
97-
private static diameters = new Set<number>([100]);
107+
private static diameters = new Set<number>([BASE_SIZE]);
98108

99109
/**
100110
* Used for storing all of the generated keyframe animations.
@@ -107,11 +117,14 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
107117
get diameter(): number {
108118
return this._diameter;
109119
}
110-
111120
set diameter(size: number) {
112-
this._setDiameterAndInitStyles(size);
121+
this._diameter = coerceNumberProperty(size);
122+
123+
if (!this._fallbackAnimation && !MatProgressSpinner.diameters.has(this._diameter)) {
124+
this._attachStyleNode();
125+
}
113126
}
114-
_diameter = this._baseSize;
127+
private _diameter = BASE_SIZE;
115128

116129
/** Stroke width of the progress spinner. */
117130
@Input()
@@ -134,7 +147,7 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
134147
}
135148
set value(newValue: number) {
136149
if (newValue != null && this.mode === 'determinate') {
137-
this._value = Math.max(0, Math.min(100, newValue));
150+
this._value = Math.max(0, Math.min(100, coerceNumberProperty(newValue)));
138151
}
139152
}
140153

@@ -154,14 +167,13 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
154167

155168
ngOnChanges(changes: SimpleChanges) {
156169
if (changes.strokeWidth || changes.diameter) {
157-
this._elementSize =
158-
this._diameter + Math.max(this.strokeWidth - this._baseStrokeWidth, 0);
170+
this._elementSize = this._diameter + Math.max(this.strokeWidth - BASE_STROKE_WIDTH, 0);
159171
}
160172
}
161173

162174
/** The radius of the spinner, adjusted for stroke width. */
163175
get _circleRadius() {
164-
return (this.diameter - this._baseStrokeWidth) / 2;
176+
return (this.diameter - BASE_STROKE_WIDTH) / 2;
165177
}
166178

167179
/** The view box of the spinner's svg element. */
@@ -194,14 +206,6 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
194206
return this.strokeWidth / this._elementSize * 100;
195207
}
196208

197-
/** Sets the diameter and adds diameter-specific styles if necessary. */
198-
private _setDiameterAndInitStyles(size: number): void {
199-
this._diameter = size;
200-
if (!MatProgressSpinner.diameters.has(this.diameter) && !this._fallbackAnimation) {
201-
this._attachStyleNode();
202-
}
203-
}
204-
205209
/** Dynamically generates a style tag containing the correct animation for this diameter. */
206210
private _attachStyleNode(): void {
207211
let styleTag = MatProgressSpinner.styleTag;

0 commit comments

Comments
 (0)