From bdf4aef92382fff388ce81ba1be6a70bbaea8b37 Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Sat, 24 Dec 2016 14:09:15 +0100 Subject: [PATCH] fix(progress-spinner): fix color input on md-spinner * Makes color application dynamic by moving it to a getter / setter. (similar to all other components & makes it easier to share the code in the future) * Now the `md-spinner` can also have a `color` binding. * Fixes the missing documentation for the `color` and `value` inputs * Removes the unused `changeDetectorRef` from the constructor DI Fixes #2393 --- .../progress-spinner/progress-spinner.spec.ts | 39 ++++++++++++++ src/lib/progress-spinner/progress-spinner.ts | 52 ++++++++++++++----- 2 files changed, 77 insertions(+), 14 deletions(-) diff --git a/src/lib/progress-spinner/progress-spinner.spec.ts b/src/lib/progress-spinner/progress-spinner.spec.ts index d23c52679316..51005bbc8175 100644 --- a/src/lib/progress-spinner/progress-spinner.spec.ts +++ b/src/lib/progress-spinner/progress-spinner.spec.ts @@ -13,8 +13,10 @@ describe('MdProgressSpinner', () => { BasicProgressSpinner, IndeterminateProgressSpinner, ProgressSpinnerWithValueAndBoundMode, + ProgressSpinnerWithColor, IndeterminateProgressSpinnerWithNgIf, SpinnerWithNgIf, + SpinnerWithColor ], }); @@ -105,6 +107,37 @@ describe('MdProgressSpinner', () => { expect(progressElement.componentInstance.interdeterminateInterval).toBeFalsy(); }); + + it('should set the color class on the md-spinner', () => { + let fixture = TestBed.createComponent(SpinnerWithColor); + fixture.detectChanges(); + + let progressElement = fixture.debugElement.query(By.css('md-spinner')); + + expect(progressElement.nativeElement.classList).toContain('md-primary'); + + fixture.debugElement.componentInstance.color = 'accent'; + fixture.detectChanges(); + + expect(progressElement.nativeElement.classList).toContain('md-accent'); + expect(progressElement.nativeElement.classList).not.toContain('md-primary'); + }); + + it('should set the color class on the md-progress-spinner', () => { + let fixture = TestBed.createComponent(ProgressSpinnerWithColor); + fixture.detectChanges(); + + let progressElement = fixture.debugElement.query(By.css('md-progress-spinner')); + + expect(progressElement.nativeElement.classList).toContain('md-primary'); + + fixture.debugElement.componentInstance.color = 'accent'; + fixture.detectChanges(); + + expect(progressElement.nativeElement.classList).toContain('md-accent'); + expect(progressElement.nativeElement.classList).not.toContain('md-primary'); + }); + }); @@ -123,3 +156,9 @@ class IndeterminateProgressSpinnerWithNgIf { } @Component({template: ``}) class SpinnerWithNgIf { } + +@Component({template: ``}) +class SpinnerWithColor { color: string = 'primary'; } + +@Component({template: ``}) +class ProgressSpinnerWithColor { color: string = 'primary'; } diff --git a/src/lib/progress-spinner/progress-spinner.ts b/src/lib/progress-spinner/progress-spinner.ts index 24538ef43e51..ad5fa2a866b4 100644 --- a/src/lib/progress-spinner/progress-spinner.ts +++ b/src/lib/progress-spinner/progress-spinner.ts @@ -3,12 +3,12 @@ import { ModuleWithProviders, Component, HostBinding, - ChangeDetectorRef, ChangeDetectionStrategy, OnDestroy, Input, ElementRef, - NgZone + NgZone, + Renderer } from '@angular/core'; import {DefaultStyleCompatibilityModeModule} from '../core'; @@ -43,10 +43,7 @@ type EasingFn = (currentTime: number, startValue: number, host: { 'role': 'progressbar', '[attr.aria-valuemin]': '_ariaValueMin', - '[attr.aria-valuemax]': '_ariaValueMax', - '[class.md-primary]': 'color == "primary"', - '[class.md-accent]': 'color == "accent"', - '[class.md-warn]': 'color == "warn"', + '[attr.aria-valuemax]': '_ariaValueMax' }, templateUrl: 'progress-spinner.html', styleUrls: ['progress-spinner.css'], @@ -62,6 +59,10 @@ export class MdProgressSpinner implements OnDestroy { /** The SVG node that is used to draw the circle. */ private _path: SVGPathElement; + private _mode: ProgressSpinnerMode = 'determinate'; + private _value: number; + private _color: string = 'primary'; + /** * Values for aria max and min are only defined as numbers when in a determinate mode. We do this * because voiceover does not report the progress indicator as indeterminate if the aria min @@ -92,8 +93,14 @@ export class MdProgressSpinner implements OnDestroy { this._cleanupIndeterminateAnimation(); } + /** The color of the progress-spinner. Can be primary, accent, or warn. */ + @Input() + get color(): string { return this._color; } + set color(value: string) { + this._updateColor(value); + } + /** Value of the progress circle. It is bound to the host as the attribute aria-valuenow. */ - private _value: number; @Input() @HostBinding('attr.aria-valuenow') get value() { @@ -128,14 +135,11 @@ export class MdProgressSpinner implements OnDestroy { } this._mode = m; } - private _mode: ProgressSpinnerMode = 'determinate'; - - @Input() color: 'primary' | 'accent' | 'warn' = 'primary'; constructor( - private _changeDetectorRef: ChangeDetectorRef, private _ngZone: NgZone, - private _elementRef: ElementRef + private _elementRef: ElementRef, + private _renderer: Renderer ) {} @@ -229,6 +233,23 @@ export class MdProgressSpinner implements OnDestroy { path.setAttribute('d', getSvgArc(currentValue, rotation)); } } + + /** + * Updates the color of the progress-spinner by adding the new palette class to the element + * and removing the old one. + */ + private _updateColor(newColor: string) { + this._setElementColor(this._color, false); + this._setElementColor(newColor, true); + this._color = newColor; + } + + /** Sets the given palette class on the component element. */ + private _setElementColor(color: string, isAdd: boolean) { + if (color != null && color != '') { + this._renderer.setElementClass(this._elementRef.nativeElement, `md-${color}`, isAdd); + } + } } @@ -245,12 +266,15 @@ export class MdProgressSpinner implements OnDestroy { 'role': 'progressbar', 'mode': 'indeterminate', }, + // Due to the class extending we need to explicitly say that the input exists. + inputs: ['color'], templateUrl: 'progress-spinner.html', styleUrls: ['progress-spinner.css'], }) export class MdSpinner extends MdProgressSpinner implements OnDestroy { - constructor(changeDetectorRef: ChangeDetectorRef, elementRef: ElementRef, ngZone: NgZone) { - super(changeDetectorRef, ngZone, elementRef); + + constructor(elementRef: ElementRef, ngZone: NgZone, renderer: Renderer) { + super(ngZone, elementRef, renderer); this.mode = 'indeterminate'; }