Skip to content

Commit 59319d0

Browse files
tinayuangaoandrewseguin
authored andcommitted
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
1 parent a87a000 commit 59319d0

File tree

3 files changed

+91
-4
lines changed

3 files changed

+91
-4
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {
10+
Directive,
11+
forwardRef,
12+
Provider,
13+
} from '@angular/core';
14+
import {
15+
CheckboxRequiredValidator,
16+
NG_VALIDATORS,
17+
} from '@angular/forms';
18+
19+
export const _MdCheckboxRequiredValidator = CheckboxRequiredValidator;
20+
21+
export const MD_CHECKBOX_REQUIRED_VALIDATOR: Provider = {
22+
provide: NG_VALIDATORS,
23+
useExisting: forwardRef(() => MdCheckboxRequiredValidator),
24+
multi: true
25+
};
26+
27+
/**
28+
* Validator for Material checkbox's required attribute in template-driven checkbox.
29+
* Current CheckboxRequiredValidator only work with `input type=checkbox` and does not
30+
* work with `md-checkbox`.
31+
*/
32+
@Directive({
33+
selector:
34+
'md-checkbox[required][formControlName],' +
35+
'mat-checkbox[required][formControlName],' +
36+
'md-checkbox[required][formControl],md-checkbox[required][ngModel],' +
37+
'mat-checkbox[required][formControl],mat-checkbox[required][ngModel]',
38+
providers: [MD_CHECKBOX_REQUIRED_VALIDATOR],
39+
host: {'[attr.required]': 'required ? "" : null'}
40+
})
41+
export class MdCheckboxRequiredValidator extends _MdCheckboxRequiredValidator {}

src/lib/checkbox/checkbox.spec.ts

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ describe('MdCheckbox', () => {
2626
SingleCheckbox,
2727
CheckboxWithFormDirectives,
2828
MultipleCheckboxes,
29+
CheckboxWithNgModel,
2930
CheckboxWithTabIndex,
3031
CheckboxWithAriaLabel,
3132
CheckboxWithAriaLabelledby,
@@ -735,6 +736,41 @@ describe('MdCheckbox', () => {
735736
});
736737
});
737738

739+
describe('with required ngModel', () => {
740+
let checkboxInstance: MdCheckbox;
741+
let inputElement: HTMLInputElement;
742+
let testComponent: CheckboxWithNgModel;
743+
744+
beforeEach(() => {
745+
fixture = TestBed.createComponent(CheckboxWithNgModel);
746+
fixture.detectChanges();
747+
748+
let checkboxDebugElement = fixture.debugElement.query(By.directive(MdCheckbox));
749+
let checkboxNativeElement = checkboxDebugElement.nativeElement;
750+
testComponent = fixture.debugElement.componentInstance;
751+
checkboxInstance = checkboxDebugElement.componentInstance;
752+
inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
753+
});
754+
755+
it('should validate with RequiredTrue validator', () => {
756+
let checkboxElement = fixture.debugElement.query(By.directive(MdCheckbox));
757+
let ngModel = checkboxElement.injector.get<NgModel>(NgModel);
758+
759+
testComponent.isRequired = true;
760+
inputElement.click();
761+
fixture.detectChanges();
762+
763+
expect(checkboxInstance.checked).toBe(true);
764+
expect(ngModel.valid).toBe(true);
765+
766+
inputElement.click();
767+
fixture.detectChanges();
768+
769+
expect(checkboxInstance.checked).toBe(false);
770+
expect(ngModel.valid).toBe(false);
771+
});
772+
});
773+
738774
describe('with name attribute', () => {
739775
beforeEach(() => {
740776
fixture = TestBed.createComponent(CheckboxWithNameAttribute);
@@ -874,7 +910,7 @@ class SingleCheckbox {
874910
onCheckboxChange: (event?: MdCheckboxChange) => void = () => {};
875911
}
876912

877-
/** Simple component for testing an MdCheckbox with ngModel. */
913+
/** Simple component for testing an MdCheckbox with ngModel in a form. */
878914
@Component({
879915
template: `
880916
<form>
@@ -886,6 +922,15 @@ class CheckboxWithFormDirectives {
886922
isGood: boolean = false;
887923
}
888924

925+
/** Simple component for testing an MdCheckbox with required ngModel. */
926+
@Component({
927+
template: `<md-checkbox [required]="isRequired" [(ngModel)]="isGood">Be good</md-checkbox>`,
928+
})
929+
class CheckboxWithNgModel {
930+
isGood: boolean = false;
931+
isRequired: boolean = true;
932+
}
933+
889934
/** Simple test component with multiple checkboxes. */
890935
@Component(({
891936
template: `

src/lib/checkbox/index.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,16 @@ import {CommonModule} from '@angular/common';
1111
import {ObserveContentModule} from '@angular/cdk/observe-content';
1212
import {MdRippleModule, MdCommonModule, FocusOriginMonitor} from '../core';
1313
import {MdCheckbox} from './checkbox';
14-
14+
import {MdCheckboxRequiredValidator} from './checkbox-required-validator';
1515

1616
@NgModule({
1717
imports: [CommonModule, MdRippleModule, MdCommonModule, ObserveContentModule],
18-
exports: [MdCheckbox, MdCommonModule],
19-
declarations: [MdCheckbox],
18+
exports: [MdCheckbox, MdCheckboxRequiredValidator, MdCommonModule],
19+
declarations: [MdCheckbox, MdCheckboxRequiredValidator],
2020
providers: [FocusOriginMonitor]
2121
})
2222
export class MdCheckboxModule {}
2323

2424

2525
export * from './checkbox';
26+
export * from './checkbox-required-validator';

0 commit comments

Comments
 (0)