diff --git a/src/demo-app/slide-toggle/slide-toggle-demo.html b/src/demo-app/slide-toggle/slide-toggle-demo.html
index cf78e71dea60..a1c6192e1563 100644
--- a/src/demo-app/slide-toggle/slide-toggle-demo.html
+++ b/src/demo-app/slide-toggle/slide-toggle-demo.html
@@ -11,4 +11,19 @@
Disable Bound
+
+
Example where the slide toggle is required inside of a form.
+
+
+
\ No newline at end of file
diff --git a/src/demo-app/slide-toggle/slide-toggle-demo.ts b/src/demo-app/slide-toggle/slide-toggle-demo.ts
index 02b758051d23..c9e3583ff5c1 100644
--- a/src/demo-app/slide-toggle/slide-toggle-demo.ts
+++ b/src/demo-app/slide-toggle/slide-toggle-demo.ts
@@ -9,4 +9,9 @@ import {Component} from '@angular/core';
})
export class SlideToggleDemo {
firstToggle: boolean;
+
+ onFormSubmit() {
+ alert(`You submitted the form.`)
+ }
+
}
diff --git a/src/lib/checkbox/checkbox.html b/src/lib/checkbox/checkbox.html
index 318176d213ee..150ea6b53dc7 100644
--- a/src/lib/checkbox/checkbox.html
+++ b/src/lib/checkbox/checkbox.html
@@ -2,6 +2,7 @@
{
}));
+ it('should forward the required attribute', () => {
+ testComponent.isRequired = true;
+ fixture.detectChanges();
+
+ expect(inputElement.required).toBe(true);
+
+ testComponent.isRequired = false;
+ fixture.detectChanges();
+
+ expect(inputElement.required).toBe(false);
+ });
+
describe('state transition css classes', () => {
it('should transition unchecked -> checked -> unchecked', () => {
testComponent.isChecked = true;
@@ -502,6 +514,7 @@ describe('MdCheckbox', () => {
{
class SingleCheckbox {
alignment: string = 'start';
isChecked: boolean = false;
+ isRequired: boolean = false;
isIndeterminate: boolean = false;
isDisabled: boolean = false;
parentElementClicked: boolean = false;
diff --git a/src/lib/checkbox/checkbox.ts b/src/lib/checkbox/checkbox.ts
index 39959ada95af..71a57559ed48 100644
--- a/src/lib/checkbox/checkbox.ts
+++ b/src/lib/checkbox/checkbox.ts
@@ -12,6 +12,7 @@ import {
ModuleWithProviders,
} from '@angular/core';
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms';
+import {BooleanFieldValue} from '@angular2-material/core/annotations/field-value';
/**
* Monotonically increasing integer used to auto-generate unique ids for checkbox components.
@@ -92,6 +93,9 @@ export class MdCheckbox implements ControlValueAccessor {
return `input-${this.id}`;
}
+ /** Whether the checkbox is required or not. */
+ @Input() @BooleanFieldValue() required: boolean = false;
+
/** Whether or not the checkbox should come before or after the label. */
@Input() align: 'start' | 'end' = 'start';
diff --git a/src/lib/slide-toggle/slide-toggle.html b/src/lib/slide-toggle/slide-toggle.html
index 6e8edf040de0..ab96e34e5e3b 100644
--- a/src/lib/slide-toggle/slide-toggle.html
+++ b/src/lib/slide-toggle/slide-toggle.html
@@ -15,6 +15,7 @@
{
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MdSlideToggleModule.forRoot(), FormsModule],
- declarations: [SlideToggleTestApp],
+ declarations: [SlideToggleTestApp, SlideToggleFormsTestApp],
});
TestBed.compileComponents();
@@ -332,6 +332,18 @@ describe('MdSlideToggle', () => {
expect(slideToggleElement.classList).toContain('md-slide-toggle-focused');
});
+ it('should forward the required attribute', () => {
+ testComponent.isRequired = true;
+ fixture.detectChanges();
+
+ expect(inputElement.required).toBe(true);
+
+ testComponent.isRequired = false;
+ fixture.detectChanges();
+
+ expect(inputElement.required).toBe(false);
+ });
+
});
describe('custom template', () => {
@@ -345,6 +357,44 @@ describe('MdSlideToggle', () => {
}));
});
+ describe('with forms', () => {
+
+ let fixture: ComponentFixture;
+ let testComponent: SlideToggleFormsTestApp;
+ let buttonElement: HTMLButtonElement;
+ let labelElement: HTMLLabelElement;
+
+ // This initialization is async() because it needs to wait for ngModel to set the initial value.
+ beforeEach(async(() => {
+ fixture = TestBed.createComponent(SlideToggleFormsTestApp);
+
+ testComponent = fixture.debugElement.componentInstance;
+
+ fixture.detectChanges();
+
+ buttonElement = fixture.debugElement.query(By.css('button')).nativeElement;
+ labelElement = fixture.debugElement.query(By.css('label')).nativeElement;
+ }));
+
+ it('should prevent the form from submit when being required', async(() => {
+
+ let fixture = TestBed.createComponent(SlideToggleFormsTestApp);
+
+ fixture.detectChanges();
+
+ buttonElement.click();
+ expect(testComponent.isSubmitted).toBe(false);
+
+ // Make the form valid by setting the slide-toggle to true.
+ labelElement.click();
+ fixture.detectChanges();
+
+ buttonElement.click();
+ expect(testComponent.isSubmitted).toBe(true);
+ }));
+
+ })
+
});
/**
@@ -361,16 +411,25 @@ function dispatchFocusChangeEvent(eventName: string, element: HTMLElement): void
@Component({
selector: 'slide-toggle-test-app',
template: `
-
+
Test Slide Toggle
+
`,
})
class SlideToggleTestApp {
isDisabled: boolean = false;
+ isRequired: boolean = false;
slideModel: boolean = false;
slideChecked: boolean = false;
slideColor: string;
@@ -385,3 +444,16 @@ class SlideToggleTestApp {
this.lastEvent = event;
}
}
+
+
+@Component({
+ selector: 'slide-toggle-forms-test-app',
+ template: `
+ `
+})
+class SlideToggleFormsTestApp {
+ isSubmitted: boolean = false;
+}
\ No newline at end of file
diff --git a/src/lib/slide-toggle/slide-toggle.ts b/src/lib/slide-toggle/slide-toggle.ts
index 1b5ea011ca33..17eb2e0ea645 100644
--- a/src/lib/slide-toggle/slide-toggle.ts
+++ b/src/lib/slide-toggle/slide-toggle.ts
@@ -66,6 +66,7 @@ export class MdSlideToggle implements AfterContentInit, ControlValueAccessor {
private _slideRenderer: SlideToggleRenderer = null;
@Input() @BooleanFieldValue() disabled: boolean = false;
+ @Input() @BooleanFieldValue() required: boolean = false;
@Input() name: string = null;
@Input() id: string = this._uniqueId;
@Input() tabIndex: number = 0;