X Tutup
Skip to content

Commit 38cb526

Browse files
committed
feat(forms/validators): pattern validator
Adding static pattern validation method to Validators Adding a directive for the pattern validator Applying clang-format rules to modified files Updating public api spec for new pattern validator Adding pattern validator to public api guard tool For #5411 Closes #5561
1 parent f6a8d04 commit 38cb526

File tree

7 files changed

+81
-4
lines changed

7 files changed

+81
-4
lines changed

modules/angular2/src/common/forms.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export {
3737
RequiredValidator,
3838
MinLengthValidator,
3939
MaxLengthValidator,
40+
PatternValidator,
4041
Validator
4142
} from './forms/directives/validators';
4243
export {FormBuilder} from './forms/form_builder';

modules/angular2/src/common/forms/directives.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ import {
1414
SelectControlValueAccessor,
1515
NgSelectOption
1616
} from './directives/select_control_value_accessor';
17-
import {RequiredValidator, MinLengthValidator, MaxLengthValidator} from './directives/validators';
17+
import {
18+
RequiredValidator,
19+
MinLengthValidator,
20+
MaxLengthValidator,
21+
PatternValidator
22+
} from './directives/validators';
1823

1924
export {NgControlName} from './directives/ng_control_name';
2025
export {NgFormControl} from './directives/ng_form_control';
@@ -34,7 +39,12 @@ export {
3439
SelectControlValueAccessor,
3540
NgSelectOption
3641
} from './directives/select_control_value_accessor';
37-
export {RequiredValidator, MinLengthValidator, MaxLengthValidator} from './directives/validators';
42+
export {
43+
RequiredValidator,
44+
MinLengthValidator,
45+
MaxLengthValidator,
46+
PatternValidator
47+
} from './directives/validators';
3848
export {NgControl} from './directives/ng_control';
3949
export {ControlValueAccessor} from './directives/control_value_accessor';
4050

@@ -73,5 +83,6 @@ export const FORM_DIRECTIVES: Type[] = CONST_EXPR([
7383

7484
RequiredValidator,
7585
MinLengthValidator,
76-
MaxLengthValidator
86+
MaxLengthValidator,
87+
PatternValidator
7788
]);

modules/angular2/src/common/forms/directives/validators.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,32 @@ export class MaxLengthValidator implements Validator {
100100

101101
validate(c: Control): {[key: string]: any} { return this._validator(c); }
102102
}
103+
104+
105+
/**
106+
* A Directive that adds the `pattern` validator to any controls marked with the
107+
* `pattern` attribute, via the {@link NG_VALIDATORS} binding. Uses attribute value
108+
* as the regex to validate Control value against. Follows pattern attribute
109+
* semantics; i.e. regex must match entire Control value.
110+
*
111+
* ### Example
112+
*
113+
* ```
114+
* <input [ngControl]="fullName" pattern="[a-zA-Z ]*">
115+
* ```
116+
*/
117+
const PATTERN_VALIDATOR = CONST_EXPR(
118+
new Provider(NG_VALIDATORS, {useExisting: forwardRef(() => PatternValidator), multi: true}));
119+
@Directive({
120+
selector: '[pattern][ngControl],[pattern][ngFormControl],[pattern][ngModel]',
121+
providers: [PATTERN_VALIDATOR]
122+
})
123+
export class PatternValidator implements Validator {
124+
private _validator: Function;
125+
126+
constructor(@Attribute("pattern") pattern: string) {
127+
this._validator = Validators.pattern(pattern);
128+
}
129+
130+
validate(c: Control): {[key: string]: any} { return this._validator(c); }
131+
}

modules/angular2/src/common/forms/validators.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,19 @@ export class Validators {
7575
};
7676
}
7777

78+
/**
79+
* Validator that requires a control to match a regex to its value.
80+
*/
81+
static pattern(pattern: string): Function {
82+
return (control: modelModule.Control): {[key: string]: any} => {
83+
if (isPresent(Validators.required(control))) return null;
84+
let regex = new RegExp(`^${pattern}$`);
85+
let v: string = control.value;
86+
return regex.test(v) ? null :
87+
{"pattern": {"requiredPattern": `^${pattern}$`, "actualValue": v}};
88+
};
89+
}
90+
7891
/**
7992
* No-op validator.
8093
*/

modules/angular2/test/common/forms/validators_spec.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,28 @@ export function main() {
6666
it("should not error on valid strings",
6767
() => { expect(Validators.maxLength(2)(new Control("aa"))).toEqual(null); });
6868

69-
it("should error on short strings", () => {
69+
it("should error on long strings", () => {
7070
expect(Validators.maxLength(2)(new Control("aaa")))
7171
.toEqual({"maxlength": {"requiredLength": 2, "actualLength": 3}});
7272
});
7373
});
7474

75+
describe("pattern", () => {
76+
it("should not error on an empty string",
77+
() => { expect(Validators.pattern("[a-zA-Z ]*")(new Control(""))).toEqual(null); });
78+
79+
it("should not error on null",
80+
() => { expect(Validators.pattern("[a-zA-Z ]*")(new Control(null))).toEqual(null); });
81+
82+
it("should not error on valid strings",
83+
() => { expect(Validators.pattern("[a-zA-Z ]*")(new Control("aaAA"))).toEqual(null); });
84+
85+
it("should error on failure to match string", () => {
86+
expect(Validators.pattern("[a-zA-Z ]*")(new Control("aaa0")))
87+
.toEqual({"pattern": {"requiredPattern": "^[a-zA-Z ]*$", "actualValue": "aaa0"}});
88+
});
89+
});
90+
7591
describe("compose", () => {
7692
it("should return null when given null",
7793
() => { expect(Validators.compose(null)).toBe(null); });

modules/angular2/test/public_api_spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,8 @@ var NG_COMMON = [
427427
'ObservableListDiffFactory.create():dart',
428428
'ObservableListDiffFactory.supports():dart',
429429
'ObservableListDiffFactory:dart',
430+
'PatternValidator',
431+
'PatternValidator.validate()',
430432
'PercentPipe',
431433
'PercentPipe.transform()',
432434
'RequiredValidator',
@@ -452,6 +454,7 @@ var NG_COMMON = [
452454
'Validators#maxLength()',
453455
'Validators#minLength()',
454456
'Validators#nullValidator()',
457+
'Validators#pattern()',
455458
'Validators#required()',
456459
'RadioButtonState',
457460
'RadioButtonState.checked',

tools/public_api_guard/public_api_spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,9 @@ const COMMON = [
772772
'NgSwitchWhen.constructor(viewContainer:ViewContainerRef, templateRef:TemplateRef, ngSwitch:NgSwitch)',
773773
'NgSwitchWhen.ngSwitchWhen=(value:any)',
774774
'NumberPipe',
775+
'PatternValidator',
776+
'PatternValidator.constructor(pattern:string)',
777+
'PatternValidator.validate(c:Control):{[key:string]:any}',
775778
'PercentPipe',
776779
'PercentPipe.transform(value:any, args:any[]):string',
777780
'RequiredValidator',
@@ -795,6 +798,7 @@ const COMMON = [
795798
'Validators.maxLength(maxLength:number):Function',
796799
'Validators.minLength(minLength:number):Function',
797800
'Validators.nullValidator(c:any):{[key:string]:boolean}',
801+
'Validators.pattern(pattern:string):Function',
798802
'Validators.required(control:Control):{[key:string]:boolean}',
799803
'RadioButtonState',
800804
'RadioButtonState.constructor(checked:boolean, value:string)',

0 commit comments

Comments
 (0)
X Tutup