diff --git a/src/lib/checkbox/checkbox.spec.ts b/src/lib/checkbox/checkbox.spec.ts
index 342c4032bed2..dfe107d0b1fc 100644
--- a/src/lib/checkbox/checkbox.spec.ts
+++ b/src/lib/checkbox/checkbox.spec.ts
@@ -8,6 +8,8 @@ import {
import {
NgControl,
FormsModule,
+ ReactiveFormsModule,
+ FormControl,
} from '@angular/forms';
import {Component, DebugElement} from '@angular/core';
import {By} from '@angular/platform-browser';
@@ -21,7 +23,7 @@ describe('MdCheckbox', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
- imports: [MdCheckboxModule.forRoot(), FormsModule],
+ imports: [MdCheckboxModule.forRoot(), FormsModule, ReactiveFormsModule],
declarations: [
SingleCheckbox,
CheckboxWithFormDirectives,
@@ -31,6 +33,7 @@ describe('MdCheckbox', () => {
CheckboxWithAriaLabelledby,
CheckboxWithNameAttribute,
CheckboxWithChangeEvent,
+ CheckboxWithFormControl,
],
});
@@ -561,18 +564,48 @@ describe('MdCheckbox', () => {
expect(inputElement.getAttribute('name')).toBe('test-name');
});
});
+
+
+ describe('with form control', () => {
+ let checkboxDebugElement: DebugElement;
+ let checkboxInstance: MdCheckbox;
+ let testComponent: CheckboxWithFormControl;
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CheckboxWithFormControl);
+ fixture.detectChanges();
+
+ checkboxDebugElement = fixture.debugElement.query(By.directive(MdCheckbox));
+ checkboxInstance = checkboxDebugElement.componentInstance;
+ testComponent = fixture.debugElement.componentInstance;
+ });
+
+ it('should toggle the disabled state', () => {
+ expect(checkboxInstance.disabled).toBe(false);
+
+ testComponent.formControl.disable();
+ fixture.detectChanges();
+
+ expect(checkboxInstance.disabled).toBe(true);
+
+ testComponent.formControl.enable();
+ fixture.detectChanges();
+
+ expect(checkboxInstance.disabled).toBe(false);
+ });
+ });
});
/** Simple component for testing a single checkbox. */
@Component({
template: `
-
-
+
`,
})
@@ -660,3 +693,11 @@ class CheckboxWithNameAttribute {}
class CheckboxWithChangeEvent {
lastEvent: MdCheckboxChange;
}
+
+/** Test component with reactive forms */
+@Component({
+ template: ``
+})
+class CheckboxWithFormControl {
+ formControl = new FormControl();
+}
diff --git a/src/lib/checkbox/checkbox.ts b/src/lib/checkbox/checkbox.ts
index a477cd575618..1f6f768f54ba 100644
--- a/src/lib/checkbox/checkbox.ts
+++ b/src/lib/checkbox/checkbox.ts
@@ -112,7 +112,7 @@ export class MdCheckbox implements ControlValueAccessor {
/** Whether or not the checkbox should come before or after the label. */
@Input() align: 'start' | 'end' = 'start';
- private _disabled: boolean;
+ private _disabled: boolean = false;
/**
* Whether the checkbox is disabled. When the checkbox is disabled it cannot be interacted with.
@@ -245,6 +245,13 @@ export class MdCheckbox implements ControlValueAccessor {
this.onTouched = fn;
}
+ /**
+ * Implemented as a part of ControlValueAccessor.
+ */
+ setDisabledState(isDisabled: boolean) {
+ this.disabled = isDisabled;
+ }
+
private _transitionCheckState(newState: TransitionCheckState) {
let oldState = this._currentCheckState;
let renderer = this._renderer;
diff --git a/src/lib/input/input.spec.ts b/src/lib/input/input.spec.ts
index d1591c615210..e6a1ed7df351 100644
--- a/src/lib/input/input.spec.ts
+++ b/src/lib/input/input.spec.ts
@@ -3,7 +3,7 @@ import {
TestBed,
} from '@angular/core/testing';
import {Component} from '@angular/core';
-import {FormsModule} from '@angular/forms';
+import {FormsModule, ReactiveFormsModule, FormControl} from '@angular/forms';
import {By} from '@angular/platform-browser';
import {MdInput, MdInputModule} from './input';
@@ -14,7 +14,7 @@ function isInternetExplorer11() {
describe('MdInput', function () {
beforeEach(async(() => {
TestBed.configureTestingModule({
- imports: [MdInputModule.forRoot(), FormsModule],
+ imports: [MdInputModule.forRoot(), FormsModule, ReactiveFormsModule],
declarations: [
MdInputNumberTypeConservedTestComponent,
MdInputPlaceholderRequiredTestComponent,
@@ -58,6 +58,7 @@ describe('MdInput', function () {
MdInputPasswordTestController,
MdInputNumberTestController,
MdTextareaWithBindings,
+ MdInputWithFormControl,
],
});
@@ -621,6 +622,27 @@ describe('MdInput', function () {
expect(inputElement.name).toBe('some-name');
});
+ it('toggles the disabled state when used with a FormControl', () => {
+ let fixture = TestBed.createComponent(MdInputWithFormControl);
+
+ fixture.detectChanges();
+
+ let input: MdInput = fixture.debugElement.query(By.directive(MdInput)).componentInstance;
+ let testComponent: MdInputWithFormControl = fixture.debugElement.componentInstance;
+
+ expect(input.disabled).toBe(false);
+
+ testComponent.formControl.disable();
+ fixture.detectChanges();
+
+ expect(input.disabled).toBe(true);
+
+ testComponent.formControl.enable();
+ fixture.detectChanges();
+
+ expect(input.disabled).toBe(false);
+ });
+
describe('md-textarea', () => {
it('supports the rows, cols, and wrap attributes', () => {
let fixture = TestBed.createComponent(MdTextareaWithBindings);
@@ -807,6 +829,11 @@ class MdInputNumberTestController {
placeholder: string = '';
}
+@Component({template: ``})
+class MdInputWithFormControl {
+ formControl = new FormControl();
+}
+
@Component({template:
``})
class MdTextareaWithBindings {
diff --git a/src/lib/input/input.ts b/src/lib/input/input.ts
index 3003b3e3e71b..13b38e26a436 100644
--- a/src/lib/input/input.ts
+++ b/src/lib/input/input.ts
@@ -293,6 +293,13 @@ export class MdInput implements ControlValueAccessor, AfterContentInit, OnChange
this._onTouchedCallback = fn;
}
+ /**
+ * Implemented as a part of ControlValueAccessor.
+ */
+ setDisabledState(isDisabled: boolean) {
+ this.disabled = isDisabled;
+ }
+
/** TODO: internal */
ngAfterContentInit() {
this._validateConstraints();
diff --git a/src/lib/radio/radio.spec.ts b/src/lib/radio/radio.spec.ts
index 5ff9427ba1af..e9553888257a 100644
--- a/src/lib/radio/radio.spec.ts
+++ b/src/lib/radio/radio.spec.ts
@@ -1,5 +1,5 @@
import {async, ComponentFixture, TestBed, fakeAsync, tick} from '@angular/core/testing';
-import {NgControl, FormsModule} from '@angular/forms';
+import {NgControl, FormsModule, ReactiveFormsModule, FormControl} from '@angular/forms';
import {Component, DebugElement} from '@angular/core';
import {By} from '@angular/platform-browser';
import {MdRadioGroup, MdRadioButton, MdRadioChange, MdRadioModule} from './radio';
@@ -9,10 +9,11 @@ describe('MdRadio', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
- imports: [MdRadioModule.forRoot(), FormsModule],
+ imports: [MdRadioModule.forRoot(), FormsModule, ReactiveFormsModule],
declarations: [
RadiosInsideRadioGroup,
RadioGroupWithNgModel,
+ RadioGroupWithFormControl,
StandaloneRadioButtons,
],
});
@@ -152,7 +153,7 @@ describe('MdRadio', () => {
expect(spies[1]).toHaveBeenCalledTimes(1);
});
- it(`should not emit a change event from the radio group when change group value
+ it(`should not emit a change event from the radio group when change group value
programmatically`, () => {
expect(groupInstance.value).toBeFalsy();
@@ -246,7 +247,7 @@ describe('MdRadio', () => {
}
}));
- it(`should update the group's selected radio to null when unchecking that radio
+ it(`should update the group's selected radio to null when unchecking that radio
programmatically`, () => {
let changeSpy = jasmine.createSpy('radio-group change listener');
groupInstance.change.subscribe(changeSpy);
@@ -420,6 +421,36 @@ describe('MdRadio', () => {
});
});
+ describe('group with FormControl', () => {
+ let fixture: ComponentFixture;
+ let groupDebugElement: DebugElement;
+ let groupInstance: MdRadioGroup;
+ let testComponent: RadioGroupWithFormControl;
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RadioGroupWithFormControl);
+ fixture.detectChanges();
+
+ testComponent = fixture.debugElement.componentInstance;
+ groupDebugElement = fixture.debugElement.query(By.directive(MdRadioGroup));
+ groupInstance = groupDebugElement.injector.get(MdRadioGroup);
+ });
+
+ it('should toggle the disabled state', () => {
+ expect(groupInstance.disabled).toBeFalsy();
+
+ testComponent.formControl.disable();
+ fixture.detectChanges();
+
+ expect(groupInstance.disabled).toBeTruthy();
+
+ testComponent.formControl.enable();
+ fixture.detectChanges();
+
+ expect(groupInstance.disabled).toBeFalsy();
+ });
+ });
+
describe('as standalone', () => {
let fixture: ComponentFixture;
let radioDebugElements: DebugElement[];
@@ -548,11 +579,11 @@ class RadiosInsideRadioGroup {
Spring
Summer
Autumn
-
+
Spring
Summer
Autumn
-
+
Baby Banana
@@ -581,6 +612,17 @@ class RadioGroupWithNgModel {
lastEvent: MdRadioChange;
}
+@Component({
+ template: `
+
+ One
+
+ `
+})
+class RadioGroupWithFormControl {
+ formControl = new FormControl();
+}
+
// TODO(jelbourn): remove everything below when Angular supports faking events.
/**
diff --git a/src/lib/radio/radio.ts b/src/lib/radio/radio.ts
index 2e94696561af..989f03ff5a9e 100644
--- a/src/lib/radio/radio.ts
+++ b/src/lib/radio/radio.ts
@@ -228,6 +228,13 @@ export class MdRadioGroup implements AfterContentInit, ControlValueAccessor {
registerOnTouched(fn: any) {
this.onTouched = fn;
}
+
+ /**
+ * Implemented as a part of ControlValueAccessor.
+ */
+ setDisabledState(isDisabled: boolean) {
+ this.disabled = isDisabled;
+ }
}
diff --git a/src/lib/slide-toggle/slide-toggle.spec.ts b/src/lib/slide-toggle/slide-toggle.spec.ts
index c1b8061c3e78..d9bf16609981 100644
--- a/src/lib/slide-toggle/slide-toggle.spec.ts
+++ b/src/lib/slide-toggle/slide-toggle.spec.ts
@@ -2,7 +2,7 @@ import {async, ComponentFixture, TestBed, fakeAsync, tick} from '@angular/core/t
import {By, HAMMER_GESTURE_CONFIG} from '@angular/platform-browser';
import {Component} from '@angular/core';
import {MdSlideToggle, MdSlideToggleChange, MdSlideToggleModule} from './slide-toggle';
-import {FormsModule, NgControl} from '@angular/forms';
+import {FormsModule, NgControl, ReactiveFormsModule, FormControl} from '@angular/forms';
import {TestGestureConfig} from '../slider/test-gesture-config';
describe('MdSlideToggle', () => {
@@ -11,8 +11,8 @@ describe('MdSlideToggle', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
- imports: [MdSlideToggleModule.forRoot(), FormsModule],
- declarations: [SlideToggleTestApp, SlideToggleFormsTestApp],
+ imports: [MdSlideToggleModule.forRoot(), FormsModule, ReactiveFormsModule],
+ declarations: [SlideToggleTestApp, SlideToggleFormsTestApp, SlideToggleWithFormControl],
providers: [
{provide: HAMMER_GESTURE_CONFIG, useFactory: () => gestureConfig = new TestGestureConfig()}
]
@@ -509,6 +509,34 @@ describe('MdSlideToggle', () => {
});
+ describe('with a FormControl', () => {
+ let fixture: ComponentFixture;
+
+ let testComponent: SlideToggleWithFormControl;
+ let slideToggle: MdSlideToggle;
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SlideToggleWithFormControl);
+ fixture.detectChanges();
+
+ testComponent = fixture.debugElement.componentInstance;
+ slideToggle = fixture.debugElement.query(By.directive(MdSlideToggle)).componentInstance;
+ });
+
+ it('should toggle the disabled state', () => {
+ expect(slideToggle.disabled).toBe(false);
+
+ testComponent.formControl.disable();
+ fixture.detectChanges();
+
+ expect(slideToggle.disabled).toBe(true);
+
+ testComponent.formControl.enable();
+ fixture.detectChanges();
+
+ expect(slideToggle.disabled).toBe(false);
+ });
+ });
});
/**
@@ -525,20 +553,20 @@ function dispatchFocusChangeEvent(eventName: string, element: HTMLElement): void
@Component({
selector: 'slide-toggle-test-app',
template: `
-
-
+
Test Slide Toggle
-
+
`,
})
class SlideToggleTestApp {
@@ -572,3 +600,14 @@ class SlideToggleFormsTestApp {
isSubmitted: boolean = false;
isRequired: boolean = false;
}
+
+
+@Component({
+ template: `
+
+ Test Slide Toggle
+ `,
+})
+class SlideToggleWithFormControl {
+ formControl = new FormControl();
+}
diff --git a/src/lib/slide-toggle/slide-toggle.ts b/src/lib/slide-toggle/slide-toggle.ts
index 66632b784156..c858a5ef0d13 100644
--- a/src/lib/slide-toggle/slide-toggle.ts
+++ b/src/lib/slide-toggle/slide-toggle.ts
@@ -174,6 +174,13 @@ export class MdSlideToggle implements AfterContentInit, ControlValueAccessor {
this.onTouched = fn;
}
+ /**
+ * Implemented as a part of ControlValueAccessor.
+ */
+ setDisabledState(isDisabled: boolean): void {
+ this.disabled = isDisabled;
+ }
+
@Input()
get checked() {
return !!this._checked;