fix(progress-spinner): coerceNumber values (#7791)

Coerces any string values that are passed to `value`, `diameter` and `strokeWidth` to numbers.
This commit is contained in:
Kristiyan Kostadinov
2017-11-10 19:07:07 +00:00
committed by Joey Perrott
parent 4b59ca1a64
commit b6712f8d13
2 changed files with 51 additions and 21 deletions
@@ -17,6 +17,7 @@ describe('MatProgressSpinner', () => {
ProgressSpinnerCustomStrokeWidth,
ProgressSpinnerCustomDiameter,
SpinnerWithColor,
ProgressSpinnerWithStringValues,
],
}).compileComponents();
}));
@@ -184,6 +185,24 @@ describe('MatProgressSpinner', () => {
expect(fixture.nativeElement.querySelector('svg').getAttribute('focusable')).toBe('false');
});
it('should handle the number inputs being passed in as strings', () => {
const fixture = TestBed.createComponent(ProgressSpinnerWithStringValues);
const spinner = fixture.debugElement.query(By.directive(MatProgressSpinner));
const svgElement = spinner.nativeElement.querySelector('svg');
fixture.detectChanges();
expect(spinner.componentInstance.diameter).toBe(37);
expect(spinner.componentInstance.strokeWidth).toBe(11);
expect(spinner.componentInstance.value).toBe(25);
expect(spinner.nativeElement.style.width).toBe('38px');
expect(spinner.nativeElement.style.height).toBe('38px');
expect(svgElement.style.width).toBe('38px');
expect(svgElement.style.height).toBe('38px');
expect(svgElement.getAttribute('viewBox')).toBe('0 0 38 38');
});
});
@@ -211,3 +230,10 @@ class SpinnerWithColor { color: string = 'primary'; }
@Component({template: `<mat-progress-spinner value="50" [color]="color"></mat-progress-spinner>`})
class ProgressSpinnerWithColor { color: string = 'primary'; }
@Component({
template: `
<mat-progress-spinner value="25" diameter="37" strokeWidth="11"></mat-progress-spinner>
`
})
class ProgressSpinnerWithStringValues { }
+25 -21
View File
@@ -26,6 +26,18 @@ import {coerceNumberProperty} from '@angular/cdk/coercion';
/** Possible mode for a progress spinner. */
export type ProgressSpinnerMode = 'determinate' | 'indeterminate';
/**
* Base reference size of the spinner.
* @docs-private
*/
const BASE_SIZE = 100;
/**
* Base reference stroke width of the spinner.
* @docs-private
*/
const BASE_STROKE_WIDTH = 10;
// Boilerplate for applying mixins to MatProgressSpinner.
/** @docs-private */
export class MatProgressSpinnerBase {
@@ -84,17 +96,15 @@ const INDETERMINATE_ANIMATION_TEMPLATE = `
export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements CanColor,
OnChanges {
private _value: number = 0;
private readonly _baseSize = 100;
private readonly _baseStrokeWidth = 10;
private _fallbackAnimation = false;
private _value = 0;
private _strokeWidth: number;
private _fallbackAnimation = false;
/** The width and height of the host element. Will grow with stroke width. **/
_elementSize = this._baseSize;
_elementSize = BASE_SIZE;
/** Tracks diameters of existing instances to de-dupe generated styles (default d = 100) */
private static diameters = new Set<number>([100]);
private static diameters = new Set<number>([BASE_SIZE]);
/**
* Used for storing all of the generated keyframe animations.
@@ -107,11 +117,14 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
get diameter(): number {
return this._diameter;
}
set diameter(size: number) {
this._setDiameterAndInitStyles(size);
this._diameter = coerceNumberProperty(size);
if (!this._fallbackAnimation && !MatProgressSpinner.diameters.has(this._diameter)) {
this._attachStyleNode();
}
}
_diameter = this._baseSize;
private _diameter = BASE_SIZE;
/** Stroke width of the progress spinner. */
@Input()
@@ -134,7 +147,7 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
}
set value(newValue: number) {
if (newValue != null && this.mode === 'determinate') {
this._value = Math.max(0, Math.min(100, newValue));
this._value = Math.max(0, Math.min(100, coerceNumberProperty(newValue)));
}
}
@@ -154,14 +167,13 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
ngOnChanges(changes: SimpleChanges) {
if (changes.strokeWidth || changes.diameter) {
this._elementSize =
this._diameter + Math.max(this.strokeWidth - this._baseStrokeWidth, 0);
this._elementSize = this._diameter + Math.max(this.strokeWidth - BASE_STROKE_WIDTH, 0);
}
}
/** The radius of the spinner, adjusted for stroke width. */
get _circleRadius() {
return (this.diameter - this._baseStrokeWidth) / 2;
return (this.diameter - BASE_STROKE_WIDTH) / 2;
}
/** The view box of the spinner's svg element. */
@@ -194,14 +206,6 @@ export class MatProgressSpinner extends _MatProgressSpinnerMixinBase implements
return this.strokeWidth / this._elementSize * 100;
}
/** Sets the diameter and adds diameter-specific styles if necessary. */
private _setDiameterAndInitStyles(size: number): void {
this._diameter = size;
if (!MatProgressSpinner.diameters.has(this.diameter) && !this._fallbackAnimation) {
this._attachStyleNode();
}
}
/** Dynamically generates a style tag containing the correct animation for this diameter. */
private _attachStyleNode(): void {
let styleTag = MatProgressSpinner.styleTag;