Skip to content

Commit

Permalink
chore: add CanDisable mixin to checkbox, radio-group, slide-toggle, a…
Browse files Browse the repository at this point in the history
…nd (angular#4209)

slider
  • Loading branch information
jelbourn authored and mmalerba committed Apr 27, 2017
1 parent bd48f39 commit 6a34f6f
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 65 deletions.
2 changes: 1 addition & 1 deletion src/lib/button/button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ export const _MdButtonMixinBase = mixinDisabled(MdButtonBase);
host: {
'[disabled]': 'disabled || null',
},
inputs: ['disabled'],
templateUrl: 'button.html',
styleUrls: ['button.css'],
inputs: ['disabled'],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
})
Expand Down
39 changes: 18 additions & 21 deletions src/lib/checkbox/checkbox.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
import {
ChangeDetectorRef,
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
forwardRef,
Input,
OnDestroy,
Output,
Renderer,
ViewEncapsulation,
forwardRef,
ViewChild,
AfterViewInit,
OnDestroy,
ViewEncapsulation,
} from '@angular/core';
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
import {coerceBooleanProperty} from '../core/coercion/boolean-property';
import {
MdRipple,
RippleRef,
FocusOriginMonitor,
FocusOrigin,
} from '../core';
import {FocusOrigin, FocusOriginMonitor, MdRipple, RippleRef} from '../core';
import {mixinDisabled, CanDisable} from '../core/common-behaviors/disabled';


/** Monotonically increasing integer used to auto-generate unique ids for checkbox components. */
Expand Down Expand Up @@ -60,6 +56,11 @@ export class MdCheckboxChange {
checked: boolean;
}

// Boilerplate for applying mixins to MdCheckbox.
export class MdCheckboxBase { }
export const _MdCheckboxMixinBase = mixinDisabled(MdCheckboxBase);


/**
* A material design checkbox component. Supports all of the functionality of an HTML5 checkbox,
* and exposes a similar API. A MdCheckbox can be either checked, unchecked, indeterminate, or
Expand All @@ -74,17 +75,19 @@ export class MdCheckboxChange {
templateUrl: 'checkbox.html',
styleUrls: ['checkbox.css'],
host: {
'[class.mat-checkbox]': 'true',
'class': 'mat-checkbox',
'[class.mat-checkbox-indeterminate]': 'indeterminate',
'[class.mat-checkbox-checked]': 'checked',
'[class.mat-checkbox-disabled]': 'disabled',
'[class.mat-checkbox-label-before]': 'labelPosition == "before"',
},
providers: [MD_CHECKBOX_CONTROL_VALUE_ACCESSOR],
inputs: ['disabled'],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MdCheckbox implements ControlValueAccessor, AfterViewInit, OnDestroy {
export class MdCheckbox extends _MdCheckboxMixinBase
implements ControlValueAccessor, AfterViewInit, OnDestroy, CanDisable {
/**
* Attached to the aria-label attribute of the host element. In most cases, arial-labelledby will
* take precedence so this may be omitted.
Expand Down Expand Up @@ -137,13 +140,6 @@ export class MdCheckbox implements ControlValueAccessor, AfterViewInit, OnDestro
/** Whether the label should appear after or before the checkbox. Defaults to 'after' */
@Input() labelPosition: 'before' | 'after' = 'after';

private _disabled: boolean = false;

/** Whether the checkbox is disabled. */
@Input()
get disabled(): boolean { return this._disabled; }
set disabled(value) { this._disabled = coerceBooleanProperty(value); }

/** Tabindex value that is passed to the underlying input element. */
@Input() tabIndex: number = 0;

Expand Down Expand Up @@ -189,6 +185,7 @@ export class MdCheckbox implements ControlValueAccessor, AfterViewInit, OnDestro
private _elementRef: ElementRef,
private _changeDetectorRef: ChangeDetectorRef,
private _focusOriginMonitor: FocusOriginMonitor) {
super();
this.color = 'accent';
}

Expand Down
24 changes: 10 additions & 14 deletions src/lib/radio/radio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
FocusOrigin,
} from '../core';
import {coerceBooleanProperty} from '../core/coercion/boolean-property';
import {mixinDisabled, CanDisable} from '../core/common-behaviors/disabled';


/**
Expand All @@ -49,6 +50,11 @@ export class MdRadioChange {
value: any;
}


// Boilerplate for applying mixins to MdRadioGroup.
export class MdRadioGroupBase { }
export const _MdRadioGroupMixinBase = mixinDisabled(MdRadioGroupBase);

/**
* A group of radio buttons. May contain one or more `<md-radio-button>` elements.
*/
Expand All @@ -59,8 +65,10 @@ export class MdRadioChange {
'role': 'radiogroup',
'[class.mat-radio-group]': 'true',
},
inputs: ['disabled'],
})
export class MdRadioGroup implements AfterContentInit, ControlValueAccessor {
export class MdRadioGroup extends _MdRadioGroupMixinBase
implements AfterContentInit, ControlValueAccessor, CanDisable {
/**
* Selected value for group. Should equal the value of the selected radio button if there *is*
* a corresponding radio button with a matching value. If there is *not* such a corresponding
Expand All @@ -72,9 +80,6 @@ export class MdRadioGroup implements AfterContentInit, ControlValueAccessor {
/** The HTML name attribute applied to radio buttons in this group. */
private _name: string = `md-radio-group-${_uniqueIdCounter++}`;

/** Disables all individual radio buttons assigned to this group. */
private _disabled: boolean = false;

/** The currently selected radio button. Should match value. */
private _selected: MdRadioButton = null;

Expand Down Expand Up @@ -127,14 +132,6 @@ export class MdRadioGroup implements AfterContentInit, ControlValueAccessor {
/** Whether the labels should appear after or before the radio-buttons. Defaults to 'after' */
@Input() labelPosition: 'before' | 'after' = 'after';

/** Whether the radio button is disabled. */
@Input()
get disabled(): boolean { return this._disabled; }
set disabled(value) {
// The presence of *any* disabled value makes the component disabled, *except* for false.
this._disabled = (value != null && value !== false) ? true : null;
}

/** Value of the radio button. */
@Input()
get value(): any { return this._value; }
Expand Down Expand Up @@ -369,8 +366,7 @@ export class MdRadioButton implements OnInit, AfterViewInit, OnDestroy {
}

set disabled(value: boolean) {
// The presence of *any* disabled value makes the component disabled, *except* for false.
this._disabled = (value != null && value !== false) ? true : null;
this._disabled = coerceBooleanProperty(value);
}

/**
Expand Down
44 changes: 23 additions & 21 deletions src/lib/slide-toggle/slide-toggle.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
import {
AfterContentInit,
ChangeDetectionStrategy,
Component,
ElementRef,
Renderer,
EventEmitter,
forwardRef,
ChangeDetectionStrategy,
Input,
OnDestroy,
Output,
EventEmitter,
AfterContentInit,
Renderer,
ViewChild,
ViewEncapsulation,
OnDestroy,
ViewEncapsulation
} from '@angular/core';
import {
applyCssTransform,
coerceBooleanProperty,
HammerInput,
FocusOriginMonitor,
FocusOrigin,
FocusOriginMonitor,
HammerInput,
MdRipple,
RippleRef
} from '../core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
import {Observable} from 'rxjs/Observable';
import {mixinDisabled, CanDisable} from '../core/common-behaviors/disabled';


export const MD_SLIDE_TOGGLE_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
Expand All @@ -39,9 +40,13 @@ export class MdSlideToggleChange {
// Increasing integer for generating unique ids for slide-toggle components.
let nextId = 0;

/**
* Two-state control, which can be also called `switch`.
*/


// Boilerplate for applying mixins to MdSlideToggle.
export class MdSlideToggleBase { }
export const _MdSlideToggleMixinBase = mixinDisabled(MdSlideToggleBase);

/** Represents a slidable "switch" toggle that can be moved between on and off. */
@Component({
moduleId: module.id,
selector: 'md-slide-toggle, mat-slide-toggle',
Expand All @@ -54,11 +59,12 @@ let nextId = 0;
templateUrl: 'slide-toggle.html',
styleUrls: ['slide-toggle.css'],
providers: [MD_SLIDE_TOGGLE_VALUE_ACCESSOR],
inputs: ['disabled'],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MdSlideToggle implements OnDestroy, AfterContentInit, ControlValueAccessor {

export class MdSlideToggle extends _MdSlideToggleMixinBase
implements OnDestroy, AfterContentInit, ControlValueAccessor, CanDisable {
private onChange = (_: any) => {};
private onTouched = () => {};

Expand All @@ -67,7 +73,6 @@ export class MdSlideToggle implements OnDestroy, AfterContentInit, ControlValueA
private _checked: boolean = false;
private _color: string;
private _slideRenderer: SlideToggleRenderer = null;
private _disabled: boolean = false;
private _required: boolean = false;
private _disableRipple: boolean = false;

Expand All @@ -92,11 +97,6 @@ export class MdSlideToggle implements OnDestroy, AfterContentInit, ControlValueA
/** Used to set the aria-labelledby attribute on the underlying input element. */
@Input('aria-labelledby') ariaLabelledby: string = null;

/** Whether the slide-toggle is disabled. */
@Input()
get disabled(): boolean { return this._disabled; }
set disabled(value) { this._disabled = coerceBooleanProperty(value); }

/** Whether the slide-toggle is required. */
@Input()
get required(): boolean { return this._required; }
Expand All @@ -121,7 +121,9 @@ export class MdSlideToggle implements OnDestroy, AfterContentInit, ControlValueA

constructor(private _elementRef: ElementRef,
private _renderer: Renderer,
private _focusOriginMonitor: FocusOriginMonitor) {}
private _focusOriginMonitor: FocusOriginMonitor) {
super();
}

ngAfterContentInit() {
this._slideRenderer = new SlideToggleRenderer(this._elementRef);
Expand Down
20 changes: 12 additions & 8 deletions src/lib/slider/slider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import {
UP_ARROW
} from '../core/keyboard/keycodes';
import {FocusOrigin, FocusOriginMonitor} from '../core/style/focus-origin-monitor';
import {mixinDisabled, CanDisable} from '../core/common-behaviors/disabled';


/**
* Visually, a 30px separation between tick marks looks best. This is very subjective but it is
Expand Down Expand Up @@ -59,6 +61,11 @@ export class MdSliderChange {
value: number;
}


// Boilerplate for applying mixins to MdSlider.
export class MdSliderBase { }
export const _MdSliderMixinBase = mixinDisabled(MdSliderBase);

/**
* Allows users to select from a range of values by moving the slider thumb. It is similar in
* behavior to the native `<input type="range">` element.
Expand All @@ -68,7 +75,6 @@ export class MdSliderChange {
selector: 'md-slider, mat-slider',
providers: [MD_SLIDER_VALUE_ACCESSOR],
host: {
'[class.mat-slider]': 'true',
'(focus)': '_onFocus()',
'(blur)': '_onBlur()',
'(click)': '_onClick($event)',
Expand All @@ -78,6 +84,7 @@ export class MdSliderChange {
'(slide)': '_onSlide($event)',
'(slideend)': '_onSlideEnd()',
'(slidestart)': '_onSlideStart($event)',
'class': 'mat-slider',
'role': 'slider',
'tabindex': '0',
'[attr.aria-disabled]': 'disabled',
Expand All @@ -99,15 +106,11 @@ export class MdSliderChange {
},
templateUrl: 'slider.html',
styleUrls: ['slider.css'],
inputs: ['disabled'],
encapsulation: ViewEncapsulation.None,
})
export class MdSlider implements ControlValueAccessor, OnDestroy {
/** Whether or not the slider is disabled. */
@Input()
get disabled(): boolean { return this._disabled; }
set disabled(value) { this._disabled = coerceBooleanProperty(value); }
private _disabled: boolean = false;

export class MdSlider extends _MdSliderMixinBase
implements ControlValueAccessor, OnDestroy, CanDisable {
/** Whether the slider is inverted. */
@Input()
get invert() { return this._invert; }
Expand Down Expand Up @@ -379,6 +382,7 @@ export class MdSlider implements ControlValueAccessor, OnDestroy {

constructor(renderer: Renderer, private _elementRef: ElementRef,
private _focusOriginMonitor: FocusOriginMonitor, @Optional() private _dir: Dir) {
super();
this._focusOriginMonitor.monitor(this._elementRef.nativeElement, renderer, true)
.subscribe((origin: FocusOrigin) => this._isActive = !!origin && origin !== 'keyboard');
this._renderer = new SliderRenderer(this._elementRef);
Expand Down

0 comments on commit 6a34f6f

Please sign in to comment.