mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
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:
committed by
Joey Perrott
parent
4b59ca1a64
commit
b6712f8d13
@@ -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 { }
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user