From 59319d03ab0a8a920aae3a3961e2065c6751a805 Mon Sep 17 00:00:00 2001 From: tinayuangao Date: Thu, 27 Jul 2017 09:43:37 -0700 Subject: [PATCH] fix(checkbox): Add RequiredTrue validator for md-checkbox (#6006) * Try to make screenshot image size same as before * change back to 1024 x 768 * Add MdCehckboxRequiredValidator * extends CheckboxRequiredValidator * Workaround for aot build error * Add doc * fix test --- .../checkbox/checkbox-required-validator.ts | 41 ++++++++++++++++ src/lib/checkbox/checkbox.spec.ts | 47 ++++++++++++++++++- src/lib/checkbox/index.ts | 7 +-- 3 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 src/lib/checkbox/checkbox-required-validator.ts diff --git a/src/lib/checkbox/checkbox-required-validator.ts b/src/lib/checkbox/checkbox-required-validator.ts new file mode 100644 index 00000000000..8c7ea92ca93 --- /dev/null +++ b/src/lib/checkbox/checkbox-required-validator.ts @@ -0,0 +1,41 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import { + Directive, + forwardRef, + Provider, +} from '@angular/core'; +import { + CheckboxRequiredValidator, + NG_VALIDATORS, +} from '@angular/forms'; + +export const _MdCheckboxRequiredValidator = CheckboxRequiredValidator; + +export const MD_CHECKBOX_REQUIRED_VALIDATOR: Provider = { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MdCheckboxRequiredValidator), + multi: true +}; + +/** + * Validator for Material checkbox's required attribute in template-driven checkbox. + * Current CheckboxRequiredValidator only work with `input type=checkbox` and does not + * work with `md-checkbox`. + */ +@Directive({ + selector: + 'md-checkbox[required][formControlName],' + + 'mat-checkbox[required][formControlName],' + + 'md-checkbox[required][formControl],md-checkbox[required][ngModel],' + + 'mat-checkbox[required][formControl],mat-checkbox[required][ngModel]', + providers: [MD_CHECKBOX_REQUIRED_VALIDATOR], + host: {'[attr.required]': 'required ? "" : null'} +}) +export class MdCheckboxRequiredValidator extends _MdCheckboxRequiredValidator {} diff --git a/src/lib/checkbox/checkbox.spec.ts b/src/lib/checkbox/checkbox.spec.ts index 0fb39a76174..baa8bae00fc 100644 --- a/src/lib/checkbox/checkbox.spec.ts +++ b/src/lib/checkbox/checkbox.spec.ts @@ -26,6 +26,7 @@ describe('MdCheckbox', () => { SingleCheckbox, CheckboxWithFormDirectives, MultipleCheckboxes, + CheckboxWithNgModel, CheckboxWithTabIndex, CheckboxWithAriaLabel, CheckboxWithAriaLabelledby, @@ -735,6 +736,41 @@ describe('MdCheckbox', () => { }); }); + describe('with required ngModel', () => { + let checkboxInstance: MdCheckbox; + let inputElement: HTMLInputElement; + let testComponent: CheckboxWithNgModel; + + beforeEach(() => { + fixture = TestBed.createComponent(CheckboxWithNgModel); + fixture.detectChanges(); + + let checkboxDebugElement = fixture.debugElement.query(By.directive(MdCheckbox)); + let checkboxNativeElement = checkboxDebugElement.nativeElement; + testComponent = fixture.debugElement.componentInstance; + checkboxInstance = checkboxDebugElement.componentInstance; + inputElement = checkboxNativeElement.querySelector('input'); + }); + + it('should validate with RequiredTrue validator', () => { + let checkboxElement = fixture.debugElement.query(By.directive(MdCheckbox)); + let ngModel = checkboxElement.injector.get(NgModel); + + testComponent.isRequired = true; + inputElement.click(); + fixture.detectChanges(); + + expect(checkboxInstance.checked).toBe(true); + expect(ngModel.valid).toBe(true); + + inputElement.click(); + fixture.detectChanges(); + + expect(checkboxInstance.checked).toBe(false); + expect(ngModel.valid).toBe(false); + }); + }); + describe('with name attribute', () => { beforeEach(() => { fixture = TestBed.createComponent(CheckboxWithNameAttribute); @@ -874,7 +910,7 @@ class SingleCheckbox { onCheckboxChange: (event?: MdCheckboxChange) => void = () => {}; } -/** Simple component for testing an MdCheckbox with ngModel. */ +/** Simple component for testing an MdCheckbox with ngModel in a form. */ @Component({ template: `
@@ -886,6 +922,15 @@ class CheckboxWithFormDirectives { isGood: boolean = false; } +/** Simple component for testing an MdCheckbox with required ngModel. */ +@Component({ + template: `Be good`, +}) +class CheckboxWithNgModel { + isGood: boolean = false; + isRequired: boolean = true; +} + /** Simple test component with multiple checkboxes. */ @Component(({ template: ` diff --git a/src/lib/checkbox/index.ts b/src/lib/checkbox/index.ts index 1bb92517f83..fe991e6c2b1 100644 --- a/src/lib/checkbox/index.ts +++ b/src/lib/checkbox/index.ts @@ -11,15 +11,16 @@ import {CommonModule} from '@angular/common'; import {ObserveContentModule} from '@angular/cdk/observe-content'; import {MdRippleModule, MdCommonModule, FocusOriginMonitor} from '../core'; import {MdCheckbox} from './checkbox'; - +import {MdCheckboxRequiredValidator} from './checkbox-required-validator'; @NgModule({ imports: [CommonModule, MdRippleModule, MdCommonModule, ObserveContentModule], - exports: [MdCheckbox, MdCommonModule], - declarations: [MdCheckbox], + exports: [MdCheckbox, MdCheckboxRequiredValidator, MdCommonModule], + declarations: [MdCheckbox, MdCheckboxRequiredValidator], providers: [FocusOriginMonitor] }) export class MdCheckboxModule {} export * from './checkbox'; +export * from './checkbox-required-validator';