mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
refactor: replace color getters and setters with mixin (#4974)
* refactor: replace color getters and setters with mixin * Replaces the color getters and setters with a Mixin function (similar as for the disabled property) * This should reduce payload and also should make it way easier to maintain the color functionality. * Address comments * Updates
This commit is contained in:
committed by
Andrew Seguin
parent
28d2ddd098
commit
3779395ef6
@@ -38,6 +38,12 @@ describe('MdButton', () => {
|
||||
fixture.detectChanges();
|
||||
expect(buttonDebugElement.nativeElement.classList.contains('mat-accent')).toBe(true);
|
||||
expect(aDebugElement.nativeElement.classList.contains('mat-accent')).toBe(true);
|
||||
|
||||
testComponent.buttonColor = null;
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(buttonDebugElement.nativeElement.classList).not.toContain('mat-accent');
|
||||
expect(aDebugElement.nativeElement.classList).not.toContain('mat-accent');
|
||||
});
|
||||
|
||||
it('should should not clear previous defined classes', () => {
|
||||
@@ -59,7 +65,6 @@ describe('MdButton', () => {
|
||||
expect(buttonDebugElement.nativeElement.classList.contains('mat-primary')).toBe(false);
|
||||
expect(buttonDebugElement.nativeElement.classList.contains('mat-accent')).toBe(true);
|
||||
expect(buttonDebugElement.nativeElement.classList.contains('custom-class')).toBe(true);
|
||||
|
||||
});
|
||||
|
||||
// Regular button tests
|
||||
|
||||
+17
-38
@@ -11,6 +11,7 @@ import {
|
||||
} from '@angular/core';
|
||||
import {coerceBooleanProperty, FocusOriginMonitor, Platform} from '../core';
|
||||
import {mixinDisabled, CanDisable} from '../core/common-behaviors/disabled';
|
||||
import {CanColor, mixinColor} from '../core/common-behaviors/color';
|
||||
|
||||
|
||||
// TODO(kara): Convert attribute selectors to classes when attr maps become available
|
||||
@@ -71,8 +72,10 @@ export class MdMiniFabCssMatStyler {}
|
||||
|
||||
|
||||
// Boilerplate for applying mixins to MdButton.
|
||||
export class MdButtonBase { }
|
||||
export const _MdButtonMixinBase = mixinDisabled(MdButtonBase);
|
||||
export class MdButtonBase {
|
||||
constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {}
|
||||
}
|
||||
export const _MdButtonMixinBase = mixinColor(mixinDisabled(MdButtonBase));
|
||||
|
||||
|
||||
/**
|
||||
@@ -89,13 +92,11 @@ export const _MdButtonMixinBase = mixinDisabled(MdButtonBase);
|
||||
},
|
||||
templateUrl: 'button.html',
|
||||
styleUrls: ['button.css'],
|
||||
inputs: ['disabled'],
|
||||
inputs: ['disabled', 'color'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class MdButton extends _MdButtonMixinBase implements OnDestroy, CanDisable {
|
||||
private _color: string;
|
||||
|
||||
export class MdButton extends _MdButtonMixinBase implements OnDestroy, CanDisable, CanColor {
|
||||
/** Whether the button is round. */
|
||||
_isRoundButton: boolean = this._hasAttributeWithPrefix('fab', 'mini-fab');
|
||||
|
||||
@@ -110,12 +111,11 @@ export class MdButton extends _MdButtonMixinBase implements OnDestroy, CanDisabl
|
||||
get disableRipple() { return this._disableRipple; }
|
||||
set disableRipple(v) { this._disableRipple = coerceBooleanProperty(v); }
|
||||
|
||||
constructor(
|
||||
private _elementRef: ElementRef,
|
||||
private _renderer: Renderer2,
|
||||
private _platform: Platform,
|
||||
private _focusOriginMonitor: FocusOriginMonitor) {
|
||||
super();
|
||||
constructor(renderer: Renderer2,
|
||||
elementRef: ElementRef,
|
||||
private _platform: Platform,
|
||||
private _focusOriginMonitor: FocusOriginMonitor) {
|
||||
super(renderer, elementRef);
|
||||
this._focusOriginMonitor.monitor(this._elementRef.nativeElement, this._renderer, true);
|
||||
}
|
||||
|
||||
@@ -123,27 +123,6 @@ export class MdButton extends _MdButtonMixinBase implements OnDestroy, CanDisabl
|
||||
this._focusOriginMonitor.stopMonitoring(this._elementRef.nativeElement);
|
||||
}
|
||||
|
||||
/** The color of the button. Can be `primary`, `accent`, or `warn`. */
|
||||
@Input()
|
||||
get color(): string { return this._color; }
|
||||
set color(value: string) { this._updateColor(value); }
|
||||
|
||||
_updateColor(newColor: string) {
|
||||
this._setElementColor(this._color, false);
|
||||
this._setElementColor(newColor, true);
|
||||
this._color = newColor;
|
||||
}
|
||||
|
||||
_setElementColor(color: string, isAdd: boolean) {
|
||||
if (color != null && color != '') {
|
||||
if (isAdd) {
|
||||
this._renderer.addClass(this._getHostElement(), `mat-${color}`);
|
||||
} else {
|
||||
this._renderer.removeClass(this._getHostElement(), `mat-${color}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Focuses the button. */
|
||||
focus(): void {
|
||||
this._getHostElement().focus();
|
||||
@@ -189,18 +168,18 @@ export class MdButton extends _MdButtonMixinBase implements OnDestroy, CanDisabl
|
||||
'[attr.aria-disabled]': '_isAriaDisabled',
|
||||
'(click)': '_haltDisabledEvents($event)',
|
||||
},
|
||||
inputs: ['disabled'],
|
||||
inputs: ['disabled', 'color'],
|
||||
templateUrl: 'button.html',
|
||||
styleUrls: ['button.css'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class MdAnchor extends MdButton {
|
||||
constructor(
|
||||
elementRef: ElementRef,
|
||||
renderer: Renderer2,
|
||||
platform: Platform,
|
||||
focusOriginMonitor: FocusOriginMonitor) {
|
||||
super(elementRef, renderer, platform, focusOriginMonitor);
|
||||
focusOriginMonitor: FocusOriginMonitor,
|
||||
elementRef: ElementRef,
|
||||
renderer: Renderer2) {
|
||||
super(renderer, elementRef, platform, focusOriginMonitor);
|
||||
}
|
||||
|
||||
/** @docs-private */
|
||||
|
||||
@@ -17,6 +17,7 @@ import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
|
||||
import {coerceBooleanProperty} from '../core/coercion/boolean-property';
|
||||
import {FocusOrigin, FocusOriginMonitor, MdRipple, RippleRef} from '../core';
|
||||
import {mixinDisabled, CanDisable} from '../core/common-behaviors/disabled';
|
||||
import {CanColor, mixinColor} from '../core/common-behaviors/color';
|
||||
|
||||
|
||||
/** Monotonically increasing integer used to auto-generate unique ids for checkbox components. */
|
||||
@@ -57,8 +58,10 @@ export class MdCheckboxChange {
|
||||
}
|
||||
|
||||
// Boilerplate for applying mixins to MdCheckbox.
|
||||
export class MdCheckboxBase { }
|
||||
export const _MdCheckboxMixinBase = mixinDisabled(MdCheckboxBase);
|
||||
export class MdCheckboxBase {
|
||||
constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {}
|
||||
}
|
||||
export const _MdCheckboxMixinBase = mixinColor(mixinDisabled(MdCheckboxBase), 'accent');
|
||||
|
||||
|
||||
/**
|
||||
@@ -82,12 +85,12 @@ export const _MdCheckboxMixinBase = mixinDisabled(MdCheckboxBase);
|
||||
'[class.mat-checkbox-label-before]': 'labelPosition == "before"',
|
||||
},
|
||||
providers: [MD_CHECKBOX_CONTROL_VALUE_ACCESSOR],
|
||||
inputs: ['disabled'],
|
||||
inputs: ['disabled', 'color'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class MdCheckbox extends _MdCheckboxMixinBase
|
||||
implements ControlValueAccessor, AfterViewInit, OnDestroy, CanDisable {
|
||||
implements ControlValueAccessor, AfterViewInit, OnDestroy, CanColor, CanDisable {
|
||||
/**
|
||||
* Attached to the aria-label attribute of the host element. In most cases, arial-labelledby will
|
||||
* take precedence so this may be omitted.
|
||||
@@ -183,19 +186,16 @@ export class MdCheckbox extends _MdCheckboxMixinBase
|
||||
|
||||
private _indeterminate: boolean = false;
|
||||
|
||||
private _color: string;
|
||||
|
||||
private _controlValueAccessorChangeFn: (value: any) => void = (value) => {};
|
||||
|
||||
/** Reference to the focused state ripple. */
|
||||
private _focusRipple: RippleRef;
|
||||
|
||||
constructor(private _renderer: Renderer2,
|
||||
private _elementRef: ElementRef,
|
||||
constructor(renderer: Renderer2,
|
||||
elementRef: ElementRef,
|
||||
private _changeDetectorRef: ChangeDetectorRef,
|
||||
private _focusOriginMonitor: FocusOriginMonitor) {
|
||||
super();
|
||||
this.color = 'accent';
|
||||
super(renderer, elementRef);
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
@@ -247,27 +247,6 @@ export class MdCheckbox extends _MdCheckboxMixinBase
|
||||
}
|
||||
}
|
||||
|
||||
/** The color of the button. Can be `primary`, `accent`, or `warn`. */
|
||||
@Input()
|
||||
get color(): string { return this._color; }
|
||||
set color(value: string) { this._updateColor(value); }
|
||||
|
||||
_updateColor(newColor: string) {
|
||||
this._setElementColor(this._color, false);
|
||||
this._setElementColor(newColor, true);
|
||||
this._color = newColor;
|
||||
}
|
||||
|
||||
_setElementColor(color: string, isAdd: boolean) {
|
||||
if (color != null && color != '') {
|
||||
if (isAdd) {
|
||||
this._renderer.addClass(this._elementRef.nativeElement, `mat-${color}`);
|
||||
} else {
|
||||
this._renderer.removeClass(this._elementRef.nativeElement, `mat-${color}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_isRippleDisabled() {
|
||||
return this.disableRipple || this.disabled;
|
||||
}
|
||||
|
||||
+13
-33
@@ -11,11 +11,19 @@ import {
|
||||
|
||||
import {Focusable} from '../core/a11y/focus-key-manager';
|
||||
import {coerceBooleanProperty} from '../core/coercion/boolean-property';
|
||||
import {CanColor, mixinColor} from '../core/common-behaviors/color';
|
||||
|
||||
export interface MdChipEvent {
|
||||
chip: MdChip;
|
||||
}
|
||||
|
||||
// Boilerplate for applying mixins to MdChip.
|
||||
export class MdChipBase {
|
||||
constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {}
|
||||
}
|
||||
export const _MdChipMixinBase = mixinColor(MdChipBase, 'primary');
|
||||
|
||||
|
||||
/**
|
||||
* Material design styled Chip component. Used inside the MdChipList component.
|
||||
*/
|
||||
@@ -23,6 +31,7 @@ export interface MdChipEvent {
|
||||
selector: `md-basic-chip, [md-basic-chip], md-chip, [md-chip],
|
||||
mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]`,
|
||||
template: `<ng-content></ng-content>`,
|
||||
inputs: ['color'],
|
||||
host: {
|
||||
'[class.mat-chip]': 'true',
|
||||
'tabindex': '-1',
|
||||
@@ -35,7 +44,7 @@ export interface MdChipEvent {
|
||||
'(click)': '_handleClick($event)'
|
||||
}
|
||||
})
|
||||
export class MdChip implements Focusable, OnInit, OnDestroy {
|
||||
export class MdChip extends _MdChipMixinBase implements Focusable, OnInit, OnDestroy, CanColor {
|
||||
|
||||
/** Whether or not the chip is disabled. Disabled chips cannot be focused. */
|
||||
protected _disabled: boolean = null;
|
||||
@@ -43,9 +52,6 @@ export class MdChip implements Focusable, OnInit, OnDestroy {
|
||||
/** Whether or not the chip is selected. */
|
||||
protected _selected: boolean = false;
|
||||
|
||||
/** The palette color of selected chips. */
|
||||
protected _color: string = 'primary';
|
||||
|
||||
/** Emitted when the chip is focused. */
|
||||
onFocus = new EventEmitter<MdChipEvent>();
|
||||
|
||||
@@ -58,11 +64,12 @@ export class MdChip implements Focusable, OnInit, OnDestroy {
|
||||
/** Emitted when the chip is destroyed. */
|
||||
@Output() destroy = new EventEmitter<MdChipEvent>();
|
||||
|
||||
constructor(protected _renderer: Renderer2, protected _elementRef: ElementRef) { }
|
||||
constructor(renderer: Renderer2, elementRef: ElementRef) {
|
||||
super(renderer, elementRef);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this._addDefaultCSSClass();
|
||||
this._updateColor(this._color);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
@@ -108,15 +115,6 @@ export class MdChip implements Focusable, OnInit, OnDestroy {
|
||||
return this.selected;
|
||||
}
|
||||
|
||||
/** The color of the chip. Can be `primary`, `accent`, or `warn`. */
|
||||
@Input() get color(): string {
|
||||
return this._color;
|
||||
}
|
||||
|
||||
set color(value: string) {
|
||||
this._updateColor(value);
|
||||
}
|
||||
|
||||
/** Allows for programmatic focusing of the chip. */
|
||||
focus(): void {
|
||||
this._elementRef.nativeElement.focus();
|
||||
@@ -147,22 +145,4 @@ export class MdChip implements Focusable, OnInit, OnDestroy {
|
||||
this._renderer.addClass(el, 'mat-basic-chip');
|
||||
}
|
||||
}
|
||||
|
||||
/** Updates the private _color variable and the native element. */
|
||||
private _updateColor(newColor: string) {
|
||||
this._setElementColor(this._color, false);
|
||||
this._setElementColor(newColor, true);
|
||||
this._color = newColor;
|
||||
}
|
||||
|
||||
/** Sets the mat-color on the native element. */
|
||||
private _setElementColor(color: string, isAdd: boolean) {
|
||||
if (color != null && color != '') {
|
||||
if (isAdd) {
|
||||
this._renderer.addClass(this._elementRef.nativeElement, `mat-${color}`);
|
||||
} else {
|
||||
this._renderer.removeClass(this._elementRef.nativeElement, `mat-${color}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import {mixinColor} from './color';
|
||||
import {ElementRef, Renderer2} from '@angular/core';
|
||||
|
||||
describe('MixinColor', () => {
|
||||
|
||||
it('should augment an existing class with a color property', () => {
|
||||
const classWithColor = mixinColor(TestClass);
|
||||
const instance = new classWithColor();
|
||||
|
||||
expect(instance.color)
|
||||
.toBeFalsy('Expected the mixed-into class to have a color property');
|
||||
|
||||
instance.color = 'accent';
|
||||
|
||||
expect(instance.color)
|
||||
.toBe('accent', 'Expected the mixed-into class to have an updated color property');
|
||||
});
|
||||
|
||||
it('should remove old color classes if new color is set', () => {
|
||||
const classWithColor = mixinColor(TestClass);
|
||||
const instance = new classWithColor();
|
||||
|
||||
expect(instance.testElement.classList.length)
|
||||
.toBe(0, 'Expected the element to not have any classes at initialization');
|
||||
|
||||
instance.color = 'primary';
|
||||
|
||||
expect(instance.testElement.classList)
|
||||
.toContain('mat-primary', 'Expected the element to have the "mat-primary" class set');
|
||||
|
||||
instance.color = 'accent';
|
||||
|
||||
expect(instance.testElement.classList)
|
||||
.not.toContain('mat-primary', 'Expected the element to no longer have "mat-primary" set.');
|
||||
expect(instance.testElement.classList)
|
||||
.toContain('mat-accent', 'Expected the element to have the "mat-accent" class set');
|
||||
});
|
||||
|
||||
it('should allow having no color set', () => {
|
||||
const classWithColor = mixinColor(TestClass);
|
||||
const instance = new classWithColor();
|
||||
|
||||
expect(instance.testElement.classList.length)
|
||||
.toBe(0, 'Expected the element to not have any classes at initialization');
|
||||
|
||||
instance.color = 'primary';
|
||||
|
||||
expect(instance.testElement.classList)
|
||||
.toContain('mat-primary', 'Expected the element to have the "mat-primary" class set');
|
||||
|
||||
instance.color = null;
|
||||
|
||||
expect(instance.testElement.classList.length)
|
||||
.toBe(0, 'Expected the element to have no color class set.');
|
||||
});
|
||||
|
||||
it('should allow having a default color if specified', () => {
|
||||
const classWithColor = mixinColor(TestClass, 'accent');
|
||||
const instance = new classWithColor();
|
||||
|
||||
|
||||
expect(instance.testElement.classList)
|
||||
.toContain('mat-accent', 'Expected the element to have the "mat-accent" class by default.');
|
||||
|
||||
instance.color = null;
|
||||
|
||||
expect(instance.testElement.classList)
|
||||
.toContain('mat-accent', 'Expected the default color "mat-accent" to be set.');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
class TestClass {
|
||||
testElement: HTMLElement = document.createElement('div');
|
||||
|
||||
/** Mock of a RendererV2 for the color mixin. */
|
||||
_renderer: Renderer2 = {
|
||||
addClass: (element: HTMLElement, className: string) => element.classList.add(className),
|
||||
removeClass: (element: HTMLElement, className: string) => element.classList.remove(className)
|
||||
} as any;
|
||||
|
||||
/** Fake instance of an ElementRef. */
|
||||
_elementRef = new ElementRef(this.testElement);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import {Constructor} from './constructor';
|
||||
import {ElementRef, Renderer2} from '@angular/core';
|
||||
|
||||
/** @docs-private */
|
||||
export interface CanColor {
|
||||
color: string;
|
||||
}
|
||||
|
||||
/** @docs-private */
|
||||
export interface HasRenderer {
|
||||
_renderer: Renderer2;
|
||||
_elementRef: ElementRef;
|
||||
}
|
||||
|
||||
/** Possible color palette values. */
|
||||
export type ThemePalette = 'primary' | 'accent' | 'warn' | null;
|
||||
|
||||
/** Mixin to augment a directive with a `color` property. */
|
||||
export function mixinColor<T extends Constructor<HasRenderer>>(base: T, defaultColor?: ThemePalette)
|
||||
: Constructor<CanColor> & T {
|
||||
return class extends base {
|
||||
private _color: ThemePalette = null;
|
||||
|
||||
get color(): ThemePalette { return this._color; }
|
||||
set color(value: ThemePalette) {
|
||||
const colorPalette = value || defaultColor;
|
||||
|
||||
if (colorPalette !== this._color) {
|
||||
if (this._color) {
|
||||
this._renderer.removeClass(this._elementRef.nativeElement, `mat-${this._color}`);
|
||||
}
|
||||
if (colorPalette) {
|
||||
this._renderer.addClass(this._elementRef.nativeElement, `mat-${colorPalette}`);
|
||||
}
|
||||
|
||||
this._color = colorPalette;
|
||||
}
|
||||
}
|
||||
|
||||
constructor(...args: any[]) {
|
||||
super(...args);
|
||||
|
||||
// Set the default color that can be specified from the mixin.
|
||||
this.color = defaultColor;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
/** @docs-private */
|
||||
export type Constructor<T> = new(...args: any[]) => T;
|
||||
@@ -1,8 +1,5 @@
|
||||
import {coerceBooleanProperty} from '../coercion/boolean-property';
|
||||
|
||||
|
||||
/** @docs-private */
|
||||
export type Constructor<T> = new(...args: any[]) => T;
|
||||
import {Constructor} from './constructor';
|
||||
|
||||
/** @docs-private */
|
||||
export interface CanDisable {
|
||||
|
||||
@@ -5,9 +5,18 @@ import {
|
||||
ElementRef,
|
||||
Renderer2,
|
||||
} from '@angular/core';
|
||||
import {CanColor, mixinColor} from '../../common-behaviors/color';
|
||||
|
||||
export type MdPseudoCheckboxState = 'unchecked' | 'checked' | 'indeterminate';
|
||||
|
||||
|
||||
// Boilerplate for applying mixins to MdChip.
|
||||
export class MdPseudoCheckboxBase {
|
||||
constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {}
|
||||
}
|
||||
export const _MdPseudoCheckboxBase = mixinColor(MdPseudoCheckboxBase, 'accent');
|
||||
|
||||
|
||||
/**
|
||||
* Component that shows a simplified checkbox without including any kind of "real" checkbox.
|
||||
* Meant to be used when the checkbox is purely decorative and a large number of them will be
|
||||
@@ -24,6 +33,7 @@ export type MdPseudoCheckboxState = 'unchecked' | 'checked' | 'indeterminate';
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
selector: 'md-pseudo-checkbox, mat-pseudo-checkbox',
|
||||
styleUrls: ['pseudo-checkbox.css'],
|
||||
inputs: ['color'],
|
||||
template: '',
|
||||
host: {
|
||||
'[class.mat-pseudo-checkbox]': 'true',
|
||||
@@ -32,29 +42,14 @@ export type MdPseudoCheckboxState = 'unchecked' | 'checked' | 'indeterminate';
|
||||
'[class.mat-pseudo-checkbox-disabled]': 'disabled',
|
||||
},
|
||||
})
|
||||
export class MdPseudoCheckbox {
|
||||
export class MdPseudoCheckbox extends _MdPseudoCheckboxBase implements CanColor {
|
||||
/** Display state of the checkbox. */
|
||||
@Input() state: MdPseudoCheckboxState = 'unchecked';
|
||||
|
||||
/** Whether the checkbox is disabled. */
|
||||
@Input() disabled: boolean = false;
|
||||
|
||||
/** Color of the checkbox. */
|
||||
@Input()
|
||||
get color(): string { return this._color; }
|
||||
set color(value: string) {
|
||||
if (value) {
|
||||
let nativeElement = this._elementRef.nativeElement;
|
||||
|
||||
this._renderer.removeClass(nativeElement, `mat-${this.color}`);
|
||||
this._renderer.addClass(nativeElement, `mat-${value}`);
|
||||
this._color = value;
|
||||
}
|
||||
}
|
||||
|
||||
private _color: string;
|
||||
|
||||
constructor(private _elementRef: ElementRef, private _renderer: Renderer2) {
|
||||
this.color = 'accent';
|
||||
constructor(elementRef: ElementRef, renderer: Renderer2) {
|
||||
super(renderer, elementRef);
|
||||
}
|
||||
}
|
||||
|
||||
+15
-26
@@ -11,6 +11,14 @@ import {
|
||||
AfterViewChecked,
|
||||
} from '@angular/core';
|
||||
import {MdIconRegistry} from './icon-registry';
|
||||
import {CanColor, mixinColor} from '../core/common-behaviors/color';
|
||||
|
||||
|
||||
// Boilerplate for applying mixins to MdIcon.
|
||||
export class MdIconBase {
|
||||
constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {}
|
||||
}
|
||||
export const _MdIconMixinBase = mixinColor(MdIconBase);
|
||||
|
||||
|
||||
/**
|
||||
@@ -51,6 +59,7 @@ import {MdIconRegistry} from './icon-registry';
|
||||
template: '<ng-content></ng-content>',
|
||||
selector: 'md-icon, mat-icon',
|
||||
styleUrls: ['icon.css'],
|
||||
inputs: ['color'],
|
||||
host: {
|
||||
'role': 'img',
|
||||
'[class.mat-icon]': 'true',
|
||||
@@ -58,8 +67,8 @@ import {MdIconRegistry} from './icon-registry';
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class MdIcon implements OnChanges, OnInit, AfterViewChecked {
|
||||
private _color: string;
|
||||
export class MdIcon extends _MdIconMixinBase implements OnChanges, OnInit, AfterViewChecked,
|
||||
CanColor {
|
||||
|
||||
/** Name of the icon in the SVG icon set. */
|
||||
@Input() svgIcon: string;
|
||||
@@ -76,34 +85,14 @@ export class MdIcon implements OnChanges, OnInit, AfterViewChecked {
|
||||
/** Screenreader label for the icon. */
|
||||
@Input('aria-label') hostAriaLabel: string = '';
|
||||
|
||||
/** Color of the icon. */
|
||||
@Input()
|
||||
get color(): string { return this._color; }
|
||||
set color(value: string) { this._updateColor(value); }
|
||||
|
||||
private _previousFontSetClass: string;
|
||||
private _previousFontIconClass: string;
|
||||
private _previousAriaLabel: string;
|
||||
|
||||
constructor(
|
||||
private _elementRef: ElementRef,
|
||||
private _renderer: Renderer2,
|
||||
private _mdIconRegistry: MdIconRegistry) { }
|
||||
|
||||
_updateColor(newColor: string) {
|
||||
this._setElementColor(this._color, false);
|
||||
this._setElementColor(newColor, true);
|
||||
this._color = newColor;
|
||||
}
|
||||
|
||||
_setElementColor(color: string, isAdd: boolean) {
|
||||
if (color != null && color != '') {
|
||||
if (isAdd) {
|
||||
this._renderer.addClass(this._elementRef.nativeElement, `mat-${color}`);
|
||||
} else {
|
||||
this._renderer.removeClass(this._elementRef.nativeElement, `mat-${color}`);
|
||||
}
|
||||
}
|
||||
constructor(private _mdIconRegistry: MdIconRegistry,
|
||||
renderer: Renderer2,
|
||||
elementRef: ElementRef) {
|
||||
super(renderer, elementRef);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
Directive,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import {CanColor, mixinColor} from '../core/common-behaviors/color';
|
||||
|
||||
|
||||
// TODO(josephperrott): Benchpress tests.
|
||||
@@ -49,6 +50,11 @@ type EasingFn = (currentTime: number, startValue: number,
|
||||
})
|
||||
export class MdProgressSpinnerCssMatStyler {}
|
||||
|
||||
// Boilerplate for applying mixins to MdProgressSpinner.
|
||||
export class MdProgressSpinnerBase {
|
||||
constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {}
|
||||
}
|
||||
export const _MdProgressSpinnerMixinBase = mixinColor(MdProgressSpinnerBase, 'primary');
|
||||
|
||||
/**
|
||||
* <md-progress-spinner> component.
|
||||
@@ -61,11 +67,14 @@ export class MdProgressSpinnerCssMatStyler {}
|
||||
'[attr.aria-valuemin]': '_ariaValueMin',
|
||||
'[attr.aria-valuemax]': '_ariaValueMax'
|
||||
},
|
||||
inputs: ['color'],
|
||||
templateUrl: 'progress-spinner.html',
|
||||
styleUrls: ['progress-spinner.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class MdProgressSpinner implements OnDestroy {
|
||||
export class MdProgressSpinner extends _MdProgressSpinnerMixinBase
|
||||
implements OnDestroy, CanColor {
|
||||
|
||||
/** The id of the last requested animation. */
|
||||
private _lastAnimationId: number = 0;
|
||||
|
||||
@@ -77,7 +86,6 @@ export class MdProgressSpinner implements OnDestroy {
|
||||
|
||||
private _mode: ProgressSpinnerMode = 'determinate';
|
||||
private _value: number;
|
||||
private _color: string = 'primary';
|
||||
|
||||
/** Stroke width of the progress spinner. By default uses 10px as stroke width. */
|
||||
@Input() strokeWidth: number = PROGRESS_SPINNER_STROKE_WIDTH;
|
||||
@@ -112,17 +120,6 @@ 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) {
|
||||
if (value) {
|
||||
this._renderer.removeClass(this._elementRef.nativeElement, `mat-${this._color}`);
|
||||
this._renderer.addClass(this._elementRef.nativeElement, `mat-${value}`);
|
||||
this._color = value;
|
||||
}
|
||||
}
|
||||
|
||||
/** Value of the progress circle. It is bound to the host as the attribute aria-valuenow. */
|
||||
@Input()
|
||||
@HostBinding('attr.aria-valuenow')
|
||||
@@ -162,10 +159,11 @@ export class MdProgressSpinner implements OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
constructor(
|
||||
private _ngZone: NgZone,
|
||||
private _elementRef: ElementRef,
|
||||
private _renderer: Renderer2) { }
|
||||
constructor(renderer: Renderer2,
|
||||
elementRef: ElementRef,
|
||||
private _ngZone: NgZone) {
|
||||
super(renderer, elementRef);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -274,13 +272,14 @@ export class MdProgressSpinner implements OnDestroy {
|
||||
'mode': 'indeterminate',
|
||||
'[class.mat-spinner]': 'true',
|
||||
},
|
||||
inputs: ['color'],
|
||||
templateUrl: 'progress-spinner.html',
|
||||
styleUrls: ['progress-spinner.css'],
|
||||
})
|
||||
export class MdSpinner extends MdProgressSpinner implements OnDestroy {
|
||||
|
||||
constructor(elementRef: ElementRef, ngZone: NgZone, renderer: Renderer2) {
|
||||
super(ngZone, elementRef, renderer);
|
||||
super(renderer, elementRef, ngZone);
|
||||
this.mode = 'indeterminate';
|
||||
}
|
||||
|
||||
|
||||
+20
-20
@@ -34,6 +34,8 @@ import {getMdSelectDynamicMultipleError, getMdSelectNonArrayValueError} from './
|
||||
import 'rxjs/add/observable/merge';
|
||||
import 'rxjs/add/operator/startWith';
|
||||
import 'rxjs/add/operator/filter';
|
||||
import {CanColor, mixinColor} from '../core/common-behaviors/color';
|
||||
import {CanDisable} from '../core/common-behaviors/disabled';
|
||||
|
||||
|
||||
/**
|
||||
@@ -95,11 +97,19 @@ export class MdSelectChange {
|
||||
/** Allowed values for the floatPlaceholder option. */
|
||||
export type MdSelectFloatPlaceholderType = 'always' | 'never' | 'auto';
|
||||
|
||||
// Boilerplate for applying mixins to MdSelect.
|
||||
export class MdSelectBase {
|
||||
constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {}
|
||||
}
|
||||
export const _MdSelectMixinBase = mixinColor(MdSelectBase, 'primary');
|
||||
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'md-select, mat-select',
|
||||
templateUrl: 'select.html',
|
||||
styleUrls: ['select.css'],
|
||||
inputs: ['color'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
host: {
|
||||
'role': 'listbox',
|
||||
@@ -122,7 +132,8 @@ export type MdSelectFloatPlaceholderType = 'always' | 'never' | 'auto';
|
||||
],
|
||||
exportAs: 'mdSelect',
|
||||
})
|
||||
export class MdSelect implements AfterContentInit, OnDestroy, OnInit, ControlValueAccessor {
|
||||
export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, OnDestroy, OnInit,
|
||||
ControlValueAccessor, CanColor {
|
||||
/** Whether or not the overlay panel is open. */
|
||||
private _panelOpen = false;
|
||||
|
||||
@@ -159,9 +170,6 @@ export class MdSelect implements AfterContentInit, OnDestroy, OnInit, ControlVal
|
||||
/** Tab index for the element. */
|
||||
private _tabIndex: number;
|
||||
|
||||
/** Theme color for the component. */
|
||||
private _color: string;
|
||||
|
||||
/**
|
||||
* The width of the trigger. Must be saved to set the min width of the overlay panel
|
||||
* and the width of the selected value.
|
||||
@@ -288,17 +296,6 @@ export class MdSelect implements AfterContentInit, OnDestroy, OnInit, ControlVal
|
||||
/** Input that can be used to specify the `aria-labelledby` attribute. */
|
||||
@Input('aria-labelledby') ariaLabelledby: string = '';
|
||||
|
||||
/** Theme color for the component. */
|
||||
@Input()
|
||||
get color(): string { return this._color; }
|
||||
set color(value: string) {
|
||||
if (value && value !== this._color) {
|
||||
this._renderer.removeClass(this._element.nativeElement, `mat-${this._color}`);
|
||||
this._renderer.addClass(this._element.nativeElement, `mat-${value}`);
|
||||
this._color = value;
|
||||
}
|
||||
}
|
||||
|
||||
/** Combined stream of all of the child options' change events. */
|
||||
get optionSelectionChanges(): Observable<MdOptionSelectionChange> {
|
||||
return Observable.merge(...this.options.map(option => option.onSelectionChange));
|
||||
@@ -313,10 +310,14 @@ export class MdSelect implements AfterContentInit, OnDestroy, OnInit, ControlVal
|
||||
/** Event emitted when the selected value has been changed by the user. */
|
||||
@Output() change: EventEmitter<MdSelectChange> = new EventEmitter<MdSelectChange>();
|
||||
|
||||
constructor(private _element: ElementRef, private _renderer: Renderer2,
|
||||
private _viewportRuler: ViewportRuler, private _changeDetectorRef: ChangeDetectorRef,
|
||||
@Optional() private _dir: Dir, @Self() @Optional() public _control: NgControl,
|
||||
constructor(private _viewportRuler: ViewportRuler,
|
||||
private _changeDetectorRef: ChangeDetectorRef,
|
||||
renderer: Renderer2,
|
||||
elementRef: ElementRef,
|
||||
@Optional() private _dir: Dir,
|
||||
@Self() @Optional() public _control: NgControl,
|
||||
@Attribute('tabindex') tabIndex: string) {
|
||||
super(renderer, elementRef);
|
||||
|
||||
if (this._control) {
|
||||
this._control.valueAccessor = this;
|
||||
@@ -327,7 +328,6 @@ export class MdSelect implements AfterContentInit, OnDestroy, OnInit, ControlVal
|
||||
|
||||
ngOnInit() {
|
||||
this._selectionModel = new SelectionModel<MdOption>(this.multiple, null, false);
|
||||
this.color = this.color || 'primary';
|
||||
}
|
||||
|
||||
ngAfterContentInit() {
|
||||
@@ -742,7 +742,7 @@ export class MdSelect implements AfterContentInit, OnDestroy, OnInit, ControlVal
|
||||
|
||||
/** Focuses the host element when the panel closes. */
|
||||
private _focusHost(): void {
|
||||
this._element.nativeElement.focus();
|
||||
this._elementRef.nativeElement.focus();
|
||||
}
|
||||
|
||||
/** Gets the index of the provided option in the option list. */
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
} from '../core';
|
||||
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
|
||||
import {mixinDisabled, CanDisable} from '../core/common-behaviors/disabled';
|
||||
import {CanColor, mixinColor} from '../core/common-behaviors/color';
|
||||
|
||||
|
||||
export const MD_SLIDE_TOGGLE_VALUE_ACCESSOR: any = {
|
||||
@@ -44,8 +45,10 @@ let nextId = 0;
|
||||
|
||||
|
||||
// Boilerplate for applying mixins to MdSlideToggle.
|
||||
export class MdSlideToggleBase { }
|
||||
export const _MdSlideToggleMixinBase = mixinDisabled(MdSlideToggleBase);
|
||||
export class MdSlideToggleBase {
|
||||
constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {}
|
||||
}
|
||||
export const _MdSlideToggleMixinBase = mixinColor(mixinDisabled(MdSlideToggleBase), 'accent');
|
||||
|
||||
/** Represents a slidable "switch" toggle that can be moved between on and off. */
|
||||
@Component({
|
||||
@@ -60,19 +63,18 @@ export const _MdSlideToggleMixinBase = mixinDisabled(MdSlideToggleBase);
|
||||
templateUrl: 'slide-toggle.html',
|
||||
styleUrls: ['slide-toggle.css'],
|
||||
providers: [MD_SLIDE_TOGGLE_VALUE_ACCESSOR],
|
||||
inputs: ['disabled'],
|
||||
inputs: ['disabled', 'color'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class MdSlideToggle extends _MdSlideToggleMixinBase
|
||||
implements OnDestroy, AfterContentInit, ControlValueAccessor, CanDisable {
|
||||
implements OnDestroy, AfterContentInit, ControlValueAccessor, CanDisable, CanColor {
|
||||
private onChange = (_: any) => {};
|
||||
private onTouched = () => {};
|
||||
|
||||
// A unique id for the slide-toggle. By default the id is auto-generated.
|
||||
private _uniqueId = `md-slide-toggle-${++nextId}`;
|
||||
private _checked: boolean = false;
|
||||
private _color: string;
|
||||
private _slideRenderer: SlideToggleRenderer = null;
|
||||
private _required: boolean = false;
|
||||
private _disableRipple: boolean = false;
|
||||
@@ -120,11 +122,11 @@ export class MdSlideToggle extends _MdSlideToggleMixinBase
|
||||
/** Reference to the ripple directive on the thumb container. */
|
||||
@ViewChild(MdRipple) _ripple: MdRipple;
|
||||
|
||||
constructor(private _elementRef: ElementRef,
|
||||
private _renderer: Renderer2,
|
||||
constructor(elementRef: ElementRef,
|
||||
renderer: Renderer2,
|
||||
private _focusOriginMonitor: FocusOriginMonitor,
|
||||
private _changeDetectorRef: ChangeDetectorRef) {
|
||||
super();
|
||||
super(renderer, elementRef);
|
||||
}
|
||||
|
||||
ngAfterContentInit() {
|
||||
@@ -210,13 +212,6 @@ export class MdSlideToggle extends _MdSlideToggleMixinBase
|
||||
}
|
||||
}
|
||||
|
||||
/** The color of the slide-toggle. Can be primary, accent, or warn. */
|
||||
@Input()
|
||||
get color(): string { return this._color; }
|
||||
set color(value: string) {
|
||||
this._updateColor(value);
|
||||
}
|
||||
|
||||
/** Toggles the checked state of the slide-toggle. */
|
||||
toggle() {
|
||||
this.checked = !this.checked;
|
||||
@@ -238,22 +233,6 @@ export class MdSlideToggle extends _MdSlideToggleMixinBase
|
||||
}
|
||||
}
|
||||
|
||||
private _updateColor(newColor: string) {
|
||||
this._setElementColor(this._color, false);
|
||||
this._setElementColor(newColor, true);
|
||||
this._color = newColor;
|
||||
}
|
||||
|
||||
private _setElementColor(color: string, isAdd: boolean) {
|
||||
if (color != null && color != '') {
|
||||
if (isAdd) {
|
||||
this._renderer.addClass(this._elementRef.nativeElement, `mat-${color}`);
|
||||
} else {
|
||||
this._renderer.removeClass(this._elementRef.nativeElement, `mat-${color}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Emits the change event to the `change` output EventEmitter */
|
||||
private _emitChangeEvent() {
|
||||
let event = new MdSlideToggleChange();
|
||||
|
||||
+12
-32
@@ -1,12 +1,12 @@
|
||||
import {
|
||||
Component,
|
||||
ChangeDetectionStrategy,
|
||||
Input,
|
||||
ViewEncapsulation,
|
||||
Directive,
|
||||
ElementRef,
|
||||
Renderer2,
|
||||
} from '@angular/core';
|
||||
import {CanColor, mixinColor} from '../core/common-behaviors/color';
|
||||
|
||||
|
||||
@Directive({
|
||||
@@ -17,11 +17,19 @@ import {
|
||||
})
|
||||
export class MdToolbarRow {}
|
||||
|
||||
// Boilerplate for applying mixins to MdToolbar.
|
||||
export class MdToolbarBase {
|
||||
constructor(public _renderer: Renderer2, public _elementRef: ElementRef) {}
|
||||
}
|
||||
export const _MdToolbarMixinBase = mixinColor(MdToolbarBase);
|
||||
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'md-toolbar, mat-toolbar',
|
||||
templateUrl: 'toolbar.html',
|
||||
styleUrls: ['toolbar.css'],
|
||||
inputs: ['color'],
|
||||
host: {
|
||||
'[class.mat-toolbar]': 'true',
|
||||
'role': 'toolbar'
|
||||
@@ -29,38 +37,10 @@ export class MdToolbarRow {}
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class MdToolbar {
|
||||
export class MdToolbar extends _MdToolbarMixinBase implements CanColor {
|
||||
|
||||
private _color: string;
|
||||
|
||||
constructor(private _elementRef: ElementRef, private _renderer: Renderer2) { }
|
||||
|
||||
/** The color of the toolbar. Can be primary, accent, or warn. */
|
||||
@Input()
|
||||
get color(): string {
|
||||
return this._color;
|
||||
}
|
||||
|
||||
set color(value: string) {
|
||||
this._updateColor(value);
|
||||
}
|
||||
|
||||
private _updateColor(newColor: string) {
|
||||
this._setElementColor(this._color, false);
|
||||
this._setElementColor(newColor, true);
|
||||
this._color = newColor;
|
||||
}
|
||||
|
||||
private _setElementColor(color: string, isAdd: boolean) {
|
||||
if (color != null && color != '') {
|
||||
let element = this._elementRef.nativeElement;
|
||||
|
||||
if (isAdd) {
|
||||
this._renderer.addClass(element, `mat-${color}`);
|
||||
} else {
|
||||
this._renderer.removeClass(element, `mat-${color}`);
|
||||
}
|
||||
}
|
||||
constructor(renderer: Renderer2, elementRef: ElementRef) {
|
||||
super(renderer, elementRef);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user