Skip to content

Commit ff223a9

Browse files
committed
Make MdRadioButton OnPush
1 parent b1e31bd commit ff223a9

File tree

1 file changed

+81
-5
lines changed

1 file changed

+81
-5
lines changed

src/lib/radio/radio.ts

Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import {
22
AfterContentInit,
3+
ChangeDetectionStrategy,
4+
ChangeDetectorRef,
35
Component,
46
ContentChildren,
57
Directive,
@@ -126,14 +128,31 @@ export class MdRadioGroup implements AfterContentInit, ControlValueAccessor {
126128
}
127129

128130
/** Whether the labels should appear after or before the radio-buttons. Defaults to 'after' */
129-
@Input() labelPosition: 'before' | 'after' = 'after';
131+
_labelPosition: 'before' | 'after' = 'after';
132+
@Input()
133+
get labelPosition(): 'before' | 'after' {
134+
return this._labelPosition;
135+
}
136+
set labelPosition(v: 'before' | 'after') {
137+
this._labelPosition = v
138+
if (this._radios) {
139+
this._radios.forEach((radio) => {
140+
radio.labelPosition = this._labelPosition;
141+
});
142+
}
143+
}
130144

131145
/** Whether the radio button is disabled. */
132146
@Input()
133147
get disabled(): boolean { return this._disabled; }
134148
set disabled(value) {
135149
// The presence of *any* disabled value makes the component disabled, *except* for false.
136150
this._disabled = (value != null && value !== false) ? true : null;
151+
if (this._radios) {
152+
this._radios.forEach((radio) => {
153+
radio.disabled = this._disabled;
154+
})
155+
}
137156
}
138157

139158
/** Value of the radio button. */
@@ -269,6 +288,7 @@ export class MdRadioGroup implements AfterContentInit, ControlValueAccessor {
269288
'[class.mat-radio-disabled]': 'disabled',
270289
'[attr.id]': 'id',
271290
}
291+
changeDetection: ChangeDetectionStrategy.OnPush,
272292
})
273293
export class MdRadioButton implements OnInit, AfterViewInit, OnDestroy {
274294

@@ -279,15 +299,67 @@ export class MdRadioButton implements OnInit, AfterViewInit, OnDestroy {
279299
@Input() name: string;
280300

281301
/** Used to set the 'aria-label' attribute on the underlying input element. */
282-
@Input('aria-label') ariaLabel: string;
302+
_ariaLabel: string;
303+
@Input('aria-label')
304+
get ariaLabel(): string {
305+
return this._ariaLabel;
306+
}
307+
set ariaLabel(value: string) {
308+
this._ariaLabel = value;
309+
this._change.markForCheck();
310+
}
283311

284312
/** The 'aria-labelledby' attribute takes precedence as the element's text alternative. */
285-
@Input('aria-labelledby') ariaLabelledby: string;
313+
_ariaLabelledby: string;
314+
@Input('aria-labelledby')
315+
get ariaLabelledby(): string {
316+
return this._ariaLabelledby;
317+
}
318+
set ariaLabelledby(value: string) {
319+
this._ariaLabelledby = value;
320+
this._change.markForCheck();
321+
}
286322

287323
/** Whether the ripple effect for this radio button is disabled. */
288324
@Input()
289325
get disableRipple(): boolean { return this._disableRipple; }
290-
set disableRipple(value) { this._disableRipple = coerceBooleanProperty(value); }
326+
set disableRipple(value) {
327+
this._disableRipple = coerceBooleanProperty(value);
328+
this._change.markForCheck();
329+
}
330+
331+
/**
332+
* Event emitted when the checked state of this radio button changes.
333+
* Change events are only emitted when the value changes due to user interaction with
334+
* the radio button (the same behavior as `<input type-"radio">`).
335+
*/
336+
@Output()
337+
change: EventEmitter<MdRadioChange> = new EventEmitter<MdRadioChange>();
338+
339+
/** The native `<input type=radio>` element */
340+
@ViewChild('input') _inputElement: ElementRef;
341+
342+
constructor(@Optional() radioGroup: MdRadioGroup,
343+
private _elementRef: ElementRef,
344+
private _renderer: Renderer,
345+
private _change: ChangeDetectorRef,
346+
public radioDispatcher: UniqueSelectionDispatcher) {
347+
// Assertions. Ideally these should be stripped out by the compiler.
348+
// TODO(jelbourn): Assert that there's no name binding AND a parent radio group.
349+
350+
this.radioGroup = radioGroup;
351+
352+
radioDispatcher.listen((id: string, name: string) => {
353+
if (id != this.id && name == this.name) {
354+
this.checked = false;
355+
}
356+
});
357+
}
358+
359+
/** ID of the native input element inside `<md-radio-button>` */
360+
get inputId(): string {
361+
return `${this.id}-input`;
362+
}
291363

292364
/** Whether this radio button is checked. */
293365
@Input()
@@ -311,6 +383,7 @@ export class MdRadioButton implements OnInit, AfterViewInit, OnDestroy {
311383
// Notify all radio buttons with the same name to un-check.
312384
this._radioDispatcher.notify(this.id, this.name);
313385
}
386+
this._change.markForCheck();
314387
}
315388
}
316389

@@ -332,7 +405,7 @@ export class MdRadioButton implements OnInit, AfterViewInit, OnDestroy {
332405
this.radioGroup.selected = this;
333406
}
334407
}
335-
408+
this._change.markForCheck();
336409
}
337410
}
338411

@@ -349,6 +422,7 @@ export class MdRadioButton implements OnInit, AfterViewInit, OnDestroy {
349422

350423
set align(v) {
351424
this.labelPosition = (v == 'start') ? 'after' : 'before';
425+
this._change.markForCheck();
352426
}
353427

354428
private _labelPosition: 'before' | 'after';
@@ -361,6 +435,7 @@ export class MdRadioButton implements OnInit, AfterViewInit, OnDestroy {
361435

362436
set labelPosition(value) {
363437
this._labelPosition = value;
438+
this._change.markForCheck();
364439
}
365440

366441
/** Whether the radio button is disabled. */
@@ -372,6 +447,7 @@ export class MdRadioButton implements OnInit, AfterViewInit, OnDestroy {
372447
set disabled(value: boolean) {
373448
// The presence of *any* disabled value makes the component disabled, *except* for false.
374449
this._disabled = (value != null && value !== false) ? true : null;
450+
this._change.markForCheck();
375451
}
376452

377453
/**

0 commit comments

Comments
 (0)