X Tutup
Skip to content

Commit e82a35d

Browse files
committed
feat(forms): add minlength and maxlength validators
Closes #4705
1 parent 50e922f commit e82a35d

File tree

8 files changed

+140
-16
lines changed

8 files changed

+140
-16
lines changed

modules/angular2/src/core/forms.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ export {
3434
} from './forms/directives/select_control_value_accessor';
3535
export {FORM_DIRECTIVES} from './forms/directives';
3636
export {NG_VALIDATORS, Validators} from './forms/validators';
37-
export {DefaultValidators} from './forms/directives/validators';
37+
export {
38+
RequiredValidator,
39+
MinLengthValidator,
40+
MaxLengthValidator
41+
} from './forms/directives/validators';
3842
export {FormBuilder} from './forms/form_builder';
3943

4044
import {FormBuilder} from './forms/form_builder';

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
SelectControlValueAccessor,
1313
NgSelectOption
1414
} from './directives/select_control_value_accessor';
15-
import {DefaultValidators} from './directives/validators';
15+
import {RequiredValidator, MinLengthValidator, MaxLengthValidator} from './directives/validators';
1616

1717
export {NgControlName} from './directives/ng_control_name';
1818
export {NgFormControl} from './directives/ng_form_control';
@@ -28,7 +28,7 @@ export {
2828
SelectControlValueAccessor,
2929
NgSelectOption
3030
} from './directives/select_control_value_accessor';
31-
export {DefaultValidators} from './directives/validators';
31+
export {RequiredValidator, MinLengthValidator, MaxLengthValidator} from './directives/validators';
3232
export {NgControlStatus} from './directives/ng_control_status';
3333

3434
/**
@@ -62,5 +62,7 @@ export const FORM_DIRECTIVES: Type[] = CONST_EXPR([
6262
SelectControlValueAccessor,
6363
NgControlStatus,
6464

65-
DefaultValidators
65+
RequiredValidator,
66+
MinLengthValidator,
67+
MaxLengthValidator
6668
]);
Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,53 @@
11
import {forwardRef, Provider, OpaqueToken} from 'angular2/src/core/di';
22
import {CONST_EXPR} from 'angular2/src/core/facade/lang';
3-
import {Directive} from 'angular2/src/core/metadata';
3+
import {Attribute, Directive} from 'angular2/src/core/metadata';
44
import {Validators, NG_VALIDATORS} from '../validators';
5+
import {NumberWrapper} from "angular2/src/core/facade/lang";
56

6-
const DEFAULT_VALIDATORS =
7+
const REQUIRED_VALIDATOR =
78
CONST_EXPR(new Provider(NG_VALIDATORS, {useValue: Validators.required, multi: true}));
89

910
@Directive({
1011
selector: '[required][ng-control],[required][ng-form-control],[required][ng-model]',
11-
bindings: [DEFAULT_VALIDATORS]
12+
providers: [REQUIRED_VALIDATOR]
1213
})
13-
export class DefaultValidators {
14+
export class RequiredValidator {
1415
}
16+
17+
function createMinLengthValidator(dir): any {
18+
return Validators.minLength(dir.minLength);
19+
}
20+
const MIN_LENGTH_VALIDATOR = CONST_EXPR(new Provider(NG_VALIDATORS, {
21+
useFactory: createMinLengthValidator,
22+
deps: [forwardRef(() => MinLengthValidator)],
23+
multi: true
24+
}));
25+
@Directive({
26+
selector: '[minlength][ng-control],[minlength][ng-form-control],[minlength][ng-model]',
27+
providers: [MIN_LENGTH_VALIDATOR]
28+
})
29+
export class MinLengthValidator {
30+
minLength: number;
31+
constructor(@Attribute("minlength") minLength: string) {
32+
this.minLength = NumberWrapper.parseInt(minLength, 10);
33+
}
34+
}
35+
36+
function createMaxLengthValidator(dir): any {
37+
return Validators.maxLength(dir.maxLength);
38+
}
39+
const MAX_LENGTH_VALIDATOR = CONST_EXPR(new Provider(NG_VALIDATORS, {
40+
useFactory: createMaxLengthValidator,
41+
deps: [forwardRef(() => MaxLengthValidator)],
42+
multi: true
43+
}));
44+
@Directive({
45+
selector: '[maxlength][ng-control],[maxlength][ng-form-control],[maxlength][ng-model]',
46+
providers: [MAX_LENGTH_VALIDATOR]
47+
})
48+
export class MaxLengthValidator {
49+
maxLength: number;
50+
constructor(@Attribute("maxlength") maxLength: string) {
51+
this.maxLength = NumberWrapper.parseInt(maxLength, 10);
52+
}
53+
}

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,26 @@ export class Validators {
2121
return isBlank(control.value) || control.value == "" ? {"required": true} : null;
2222
}
2323

24+
static minLength(minLength: number): Function {
25+
return (control: modelModule.Control): {[key: string]: any} => {
26+
if (isPresent(Validators.required(control))) return null;
27+
var v: string = control.value;
28+
return v.length < minLength ?
29+
{"minlength": {"requiredLength": minLength, "actualLength": v.length}} :
30+
null;
31+
};
32+
}
33+
34+
static maxLength(maxLength: number): Function {
35+
return (control: modelModule.Control): {[key: string]: any} => {
36+
if (isPresent(Validators.required(control))) return null;
37+
var v: string = control.value;
38+
return v.length > maxLength ?
39+
{"maxlength": {"requiredLength": maxLength, "actualLength": v.length}} :
40+
null;
41+
};
42+
}
43+
2444
static nullValidator(c: any): {[key: string]: boolean} { return null; }
2545

2646
static compose(validators: Function[]): Function {

modules/angular2/test/core/forms/directives_spec.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import {
2828
NgForm,
2929
NgModel,
3030
NgFormControl,
31-
DefaultValidators,
3231
NgControl,
3332
DefaultValueAccessor,
3433
CheckboxControlValueAccessor,

modules/angular2/test/core/forms/integration_spec.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -349,23 +349,43 @@ export function main() {
349349
describe("validations", () => {
350350
it("should use validators defined in html",
351351
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
352-
var form = new ControlGroup({"login": new Control("aa")});
352+
var form = new ControlGroup(
353+
{"login": new Control(""), "min": new Control(""), "max": new Control("")});
353354

354355
var t = `<div [ng-form-model]="form">
355356
<input type="text" ng-control="login" required>
357+
<input type="text" ng-control="min" minlength="3">
358+
<input type="text" ng-control="max" maxlength="3">
356359
</div>`;
357360

358361
tcb.overrideTemplate(MyComp, t).createAsync(MyComp).then((rootTC) => {
359362
rootTC.debugElement.componentInstance.form = form;
360363
rootTC.detectChanges();
361-
expect(form.valid).toEqual(true);
362364

363-
var input = rootTC.debugElement.query(By.css("input"));
365+
var required = rootTC.debugElement.query(By.css("[required]"));
366+
var minLength = rootTC.debugElement.query(By.css("[minlength]"));
367+
var maxLength = rootTC.debugElement.query(By.css("[maxlength]"));
364368

365-
input.nativeElement.value = "";
366-
dispatchEvent(input.nativeElement, "change");
369+
required.nativeElement.value = "";
370+
minLength.nativeElement.value = "1";
371+
maxLength.nativeElement.value = "1234";
372+
dispatchEvent(required.nativeElement, "change");
373+
dispatchEvent(minLength.nativeElement, "change");
374+
dispatchEvent(maxLength.nativeElement, "change");
375+
376+
expect(form.hasError("required", ["login"])).toEqual(true);
377+
expect(form.hasError("minlength", ["min"])).toEqual(true);
378+
expect(form.hasError("maxlength", ["max"])).toEqual(true);
379+
380+
required.nativeElement.value = "1";
381+
minLength.nativeElement.value = "123";
382+
maxLength.nativeElement.value = "123";
383+
dispatchEvent(required.nativeElement, "change");
384+
dispatchEvent(minLength.nativeElement, "change");
385+
dispatchEvent(maxLength.nativeElement, "change");
386+
387+
expect(form.valid).toEqual(true);
367388

368-
expect(form.valid).toEqual(false);
369389
async.done();
370390
});
371391
}));

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,38 @@ export function main() {
3232
() => { expect(Validators.required(new Control("not empty"))).toEqual(null); });
3333
});
3434

35+
describe("minLength", () => {
36+
it("should not error on an empty string",
37+
() => { expect(Validators.minLength(2)(new Control(""))).toEqual(null); });
38+
39+
it("should not error on null",
40+
() => { expect(Validators.minLength(2)(new Control(null))).toEqual(null); });
41+
42+
it("should not error on valid strings",
43+
() => { expect(Validators.minLength(2)(new Control("aa"))).toEqual(null); });
44+
45+
it("should error on short strings", () => {
46+
expect(Validators.minLength(2)(new Control("a")))
47+
.toEqual({"minlength": {"requiredLength": 2, "actualLength": 1}});
48+
});
49+
});
50+
51+
describe("maxLength", () => {
52+
it("should not error on an empty string",
53+
() => { expect(Validators.maxLength(2)(new Control(""))).toEqual(null); });
54+
55+
it("should not error on null",
56+
() => { expect(Validators.maxLength(2)(new Control(null))).toEqual(null); });
57+
58+
it("should not error on valid strings",
59+
() => { expect(Validators.maxLength(2)(new Control("aa"))).toEqual(null); });
60+
61+
it("should error on short strings", () => {
62+
expect(Validators.maxLength(2)(new Control("aaa")))
63+
.toEqual({"maxlength": {"requiredLength": 2, "actualLength": 3}});
64+
});
65+
});
66+
3567
describe("compose", () => {
3668
it("should return a null validator when given null",
3769
() => { expect(Validators.compose(null)).toBe(Validators.nullValidator); });

modules/angular2/test/public_api_spec.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,13 @@ var NG_API = [
396396
'DebugElement.queryAll()',
397397
'DecimalPipe',
398398
'DecimalPipe.transform()',
399-
'DefaultValidators',
399+
'RequiredValidator',
400+
'MinLengthValidator',
401+
'MinLengthValidator.minLength',
402+
'MinLengthValidator.minLength=',
403+
'MaxLengthValidator',
404+
'MaxLengthValidator.maxLength',
405+
'MaxLengthValidator.maxLength=',
400406
'DefaultValueAccessor',
401407
'DefaultValueAccessor.onChange',
402408
'DefaultValueAccessor.onChange=',
@@ -995,6 +1001,8 @@ var NG_API = [
9951001
'Validators#group()',
9961002
'Validators#nullValidator()',
9971003
'Validators#required()',
1004+
'Validators#minLength()',
1005+
'Validators#maxLength()',
9981006
'Validators',
9991007
'View',
10001008
'View.directives',

0 commit comments

Comments
 (0)
X Tutup