diff --git a/README.md b/README.md index 841c8b0..4304f89 100644 --- a/README.md +++ b/README.md @@ -205,9 +205,14 @@ export class AppModule { ### equalTo ```html - - -

error message

+
+
+ +

required error

+ +

equalTo error

+
+
``` ## model driven @@ -254,51 +259,139 @@ export class AppComponent { ```html -

error message

+

error message

``` -### examples +### rangeLength + +```javascript +new FormControl('', CustomValidators.rangeLength([5, 9])) +``` + +### min + +```javascript +new FormControl('', CustomValidators.min(10)) +``` + +### max + +```javascript +new FormControl('', CustomValidators.max(20)) +``` + +### range + +```javascript +new FormControl('', CustomValidators.range([10, 20])) +``` + +### digits + +```javascript +new FormControl('', CustomValidators.digits) +``` + +### number + +```javascript +new FormControl('', CustomValidators.number) +``` + +### url + +```javascript +new FormControl('', CustomValidators.url) +``` + +### email ```javascript -CustomValidators.rangeLength([5, 9]) +new FormControl('', CustomValidators.email) +``` -CustomValidators.min(10) +### date -CustomValidators.max(20) +```javascript +new FormControl('', CustomValidators.date) +``` -CustomValidators.range([10, 20]) +### dateISO -CustomValidators.digits +```javascript +new FormControl('', CustomValidators.dateISO) +``` -CustomValidators.number +### creditCard -CustomValidators.url +```javascript +new FormControl('', CustomValidators.creditCard) +``` -CustomValidators.email +### json -CustomValidators.date +```javascript +new FormControl('', CustomValidators.json) +``` -CustomValidators.dateISO +### base64 -CustomValidators.creditCard +```javascript +new FormControl('', CustomValidators.base64) +``` -CustomValidators.json +### phone -CustomValidators.base64 +```javascript +new FormControl('', CustomValidators.phone('zh-CN')) +``` -CustomValidators.phonoe('zh-CN') +### uuid -CustomValidators.uuid('3') +```javascript +new FormControl('', CustomValidators.uuid('3')) +``` -CustomValidators.equal('xxx') +### equal -var password = new FormControl('', Validators.required); -var certainPassword = new FormControl('', CustomValidators.equalTo(password)); +```javascript +new FormControl('', CustomValidators.equal('xxx')) +``` -this.form = new FormGroup({ - password: password, - certainPassword: certainPassword -}); +### equalTo + +```javascript +@Component({ + selector: 'app', + template: require('./app.html') +}) +export class AppComponent implements OnInit { + form: FormGroup; + + ngOnInit() { + var password = new FormControl('', Validators.required); + var certainPassword = new FormControl(''); + + this.form = new FormGroup({ + passwordGroup: new FormGroup({ + password: password, + certainPassword: certainPassword + }, CustomValidators.equalTo) + }); + } +} +``` + +```html +
+
+ +

required error

+ +

equalTo error

+
+ +
``` # License diff --git a/example/src/app.component.ts b/example/src/app.component.ts index 7d88b66..aaa8d00 100644 --- a/example/src/app.component.ts +++ b/example/src/app.component.ts @@ -4,27 +4,25 @@ import { Validators, FormControl, FormGroup } from '@angular/forms'; import { CustomValidators } from '../../src'; @Component({ - selector: 'app', - template: require('./app.html') + selector: 'app', + template: require('./app.html') }) export class AppComponent implements OnInit { - form: FormGroup; + form: FormGroup; - constructor() { - } + ngOnInit() { + var password = new FormControl('', Validators.required); + var certainPassword = new FormControl(''); - ngOnInit() { - var password = new FormControl('', Validators.required); - var certainPassword = new FormControl('', CustomValidators.equalTo(password)); - - this.form = new FormGroup({ - password: password, - certainPassword: certainPassword - }); - } - - onSubmit() { - console.log(this.form); - } + this.form = new FormGroup({ + passwordGroup: new FormGroup({ + password: password, + certainPassword: certainPassword + }, CustomValidators.equalTo) + }); + } + onSubmit(form) { + console.log(form); + } } \ No newline at end of file diff --git a/example/src/app.html b/example/src/app.html index 5d8cb6c..aa9c576 100644 --- a/example/src/app.html +++ b/example/src/app.html @@ -1,48 +1,50 @@ -
- - - + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + +

equalTo to password

- -

required error

- -

equalTo error

- + +

required error

+ +

equalTo error

+
+
\ No newline at end of file diff --git a/example/src/app.module.ts b/example/src/app.module.ts index b68f31c..4f1898c 100644 --- a/example/src/app.module.ts +++ b/example/src/app.module.ts @@ -1,13 +1,14 @@ import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; -import { ReactiveFormsModule } from '@angular/forms'; +import { ReactiveFormsModule, FormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; +import { CustomFormsModule } from '../../src'; @NgModule({ - imports: [BrowserModule, ReactiveFormsModule], - declarations: [AppComponent], - bootstrap: [AppComponent] + imports: [BrowserModule, ReactiveFormsModule, FormsModule, CustomFormsModule], + declarations: [AppComponent], + bootstrap: [AppComponent] }) export class AppModule { } \ No newline at end of file diff --git a/package.json b/package.json index 4502932..3d6cec5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ng2-validation", - "version": "1.4.2", + "version": "1.5.2", "description": "angular2 validation", "main": "dist/index.js", "typings": "dist/index.d.ts", diff --git a/src/custom-validators.ts b/src/custom-validators.ts index c171093..ee4b162 100644 --- a/src/custom-validators.ts +++ b/src/custom-validators.ts @@ -1,267 +1,272 @@ -import { ValidatorFn, AbstractControl, Validators } from '@angular/forms'; +import { ValidatorFn, AbstractControl, Validators, FormGroup } from '@angular/forms'; -import { isPresent, isString } from './lang'; - -export type EqualValueType = string | boolean | number; +import { isPresent } from './lang'; export class CustomValidators { - /** - * Validator that requires controls to have a value of a range length. - */ - static rangeLength(rangeLength: Array): ValidatorFn { - return (control: AbstractControl): {[key: string]: any} => { - if (isPresent(Validators.required(control))) return null; - - let v: string = control.value; - return v.length >= rangeLength[0] && v.length <= rangeLength[1] ? null : {'rangeLength': true}; - }; - } - - /** - * Validator that requires controls to have a value of a min value. - */ - static min(min: number): ValidatorFn { - return (control: AbstractControl): {[key: string]: any} => { - if (isPresent(Validators.required(control))) return null; - - let v: number = control.value; - return v >= min ? null : {'min': true}; - }; - } - - /** - * Validator that requires controls to have a value of a max value. - */ - static max(max: number): ValidatorFn { - return (control: AbstractControl): {[key: string]: any} => { - if (isPresent(Validators.required(control))) return null; - - let v: number = control.value; - return v <= max ? null : {'max': true}; - }; - } - - /** - * Validator that requires controls to have a value of a range value. - */ - static range(range: Array): ValidatorFn { - return (control: AbstractControl): {[key: string]: any} => { - if (isPresent(Validators.required(control))) return null; - - let v: number = control.value; - return v >= range[0] && v <= range[1] ? null : {'range': true}; - }; - } - - /** - * Validator that requires controls to have a value of digits. - */ - static digits(control: AbstractControl): {[key: string]: boolean} { - if (isPresent(Validators.required(control))) return null; - - let v: string = control.value; - return /^\d+$/.test(v) ? null : {'digits': true}; - } - - /** - * Validator that requires controls to have a value of number. - */ - static number(control: AbstractControl): {[key: string]: boolean} { - if (isPresent(Validators.required(control))) return null; - - let v: string = control.value; - return /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(v) ? null : {'number': true}; - } - - /** - * Validator that requires controls to have a value of url. - */ - static url(control: AbstractControl): {[key: string]: boolean} { - if (isPresent(Validators.required(control))) return null; - - let v: string = control.value; - return /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(v) ? null : {'url': true}; - } - - /** - * Validator that requires controls to have a value of email. - */ - static email(control: AbstractControl): {[key: string]: boolean} { - if (isPresent(Validators.required(control))) return null; - - let v: string = control.value; - return /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(v) ? null : {'email': true}; - } - - /** - * Validator that requires controls to have a value of date. - */ - static date(control: AbstractControl): {[key: string]: boolean} { - if (isPresent(Validators.required(control))) return null; - - let v: string = control.value; - return !/Invalid|NaN/.test(new Date(v).toString()) ? null : {'date': true}; + /** + * Validator that requires controls to have a value of a range length. + */ + static rangeLength(rangeLength: Array): ValidatorFn { + return (control: AbstractControl): {[key: string]: any} => { + if (isPresent(Validators.required(control))) return null; + + let v: string = control.value; + return v.length >= rangeLength[0] && v.length <= rangeLength[1] ? null : {'rangeLength': true}; + }; + } + + /** + * Validator that requires controls to have a value of a min value. + */ + static min(min: number): ValidatorFn { + return (control: AbstractControl): {[key: string]: any} => { + if (isPresent(Validators.required(control))) return null; + + let v: number = control.value; + return v >= min ? null : {'min': true}; + }; + } + + /** + * Validator that requires controls to have a value of a max value. + */ + static max(max: number): ValidatorFn { + return (control: AbstractControl): {[key: string]: any} => { + if (isPresent(Validators.required(control))) return null; + + let v: number = control.value; + return v <= max ? null : {'max': true}; + }; + } + + /** + * Validator that requires controls to have a value of a range value. + */ + static range(range: Array): ValidatorFn { + return (control: AbstractControl): {[key: string]: any} => { + if (isPresent(Validators.required(control))) return null; + + let v: number = control.value; + return v >= range[0] && v <= range[1] ? null : {'range': true}; + }; + } + + /** + * Validator that requires controls to have a value of digits. + */ + static digits(control: AbstractControl): {[key: string]: boolean} { + if (isPresent(Validators.required(control))) return null; + + let v: string = control.value; + return /^\d+$/.test(v) ? null : {'digits': true}; + } + + /** + * Validator that requires controls to have a value of number. + */ + static number(control: AbstractControl): {[key: string]: boolean} { + if (isPresent(Validators.required(control))) return null; + + let v: string = control.value; + return /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(v) ? null : {'number': true}; + } + + /** + * Validator that requires controls to have a value of url. + */ + static url(control: AbstractControl): {[key: string]: boolean} { + if (isPresent(Validators.required(control))) return null; + + let v: string = control.value; + return /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(v) ? null : {'url': true}; + } + + /** + * Validator that requires controls to have a value of email. + */ + static email(control: AbstractControl): {[key: string]: boolean} { + if (isPresent(Validators.required(control))) return null; + + let v: string = control.value; + return /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(v) ? null : {'email': true}; + } + + /** + * Validator that requires controls to have a value of date. + */ + static date(control: AbstractControl): {[key: string]: boolean} { + if (isPresent(Validators.required(control))) return null; + + let v: string = control.value; + return !/Invalid|NaN/.test(new Date(v).toString()) ? null : {'date': true}; + } + + /** + * Validator that requires controls to have a value of dateISO. + */ + static dateISO(control: AbstractControl): {[key: string]: boolean} { + if (isPresent(Validators.required(control))) return null; + + let v: string = control.value; + return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(v) ? null : {'dateISO': true}; + } + + /** + * Validator that requires controls to have a value of creditCard. + */ + static creditCard(control: AbstractControl): {[key: string]: boolean} { + if (isPresent(Validators.required(control))) return null; + + let v: string = control.value; + + let sanitized = v.replace(/[^0-9]+/g, ''); + + // problem with chrome + if (!(/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/.test(sanitized))) { + return {'creditCard': true}; } - /** - * Validator that requires controls to have a value of dateISO. - */ - static dateISO(control: AbstractControl): {[key: string]: boolean} { - if (isPresent(Validators.required(control))) return null; - - let v: string = control.value; - return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(v) ? null : {'dateISO': true}; - } - - /** - * Validator that requires controls to have a value of creditCard. - */ - static creditCard(control: AbstractControl): {[key: string]: boolean} { - if (isPresent(Validators.required(control))) return null; - - let v: string = control.value; - - let sanitized = v.replace(/[^0-9]+/g, ''); - - // problem with chrome - if (!(/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/.test(sanitized))) { - return {'creditCard': true}; - } - - let sum = 0; - let digit; - let tmpNum; - let shouldDouble; - for (let i = sanitized.length - 1; i >= 0; i--) { - digit = sanitized.substring(i, (i + 1)); - tmpNum = parseInt(digit, 10); - if (shouldDouble) { - tmpNum *= 2; - if (tmpNum >= 10) { - sum += ((tmpNum % 10) + 1); - } else { - sum += tmpNum; - } - } else { - sum += tmpNum; - } - shouldDouble = !shouldDouble; - } - - if (Boolean((sum % 10) === 0 ? sanitized : false)) { - return null; - } - - return {'creditCard': true}; - } - - /** - * Validator that requires controls to have a value of JSON. - */ - static json(control: AbstractControl): {[key: string]: boolean} { - if (isPresent(Validators.required(control))) return null; - - let v: string = control.value; - - try { - let obj = JSON.parse(v); - - if (Boolean(obj) && typeof obj === 'object') { - return null; - } - } catch (e) { + let sum = 0; + let digit; + let tmpNum; + let shouldDouble; + for (let i = sanitized.length - 1; i >= 0; i--) { + digit = sanitized.substring(i, (i + 1)); + tmpNum = parseInt(digit, 10); + if (shouldDouble) { + tmpNum *= 2; + if (tmpNum >= 10) { + sum += ((tmpNum % 10) + 1); + } else { + sum += tmpNum; } - return {'json': true}; + } else { + sum += tmpNum; + } + shouldDouble = !shouldDouble; } - /** - * Validator that requires controls to have a value of base64. - */ - static base64(control: AbstractControl): {[key: string]: boolean} { - if (isPresent(Validators.required(control))) return null; - - let v: string = control.value; - return /^(?:[A-Z0-9+\/]{4})*(?:[A-Z0-9+\/]{2}==|[A-Z0-9+\/]{3}=|[A-Z0-9+\/]{4})$/i.test(v) ? null : {'base64': true}; + if (Boolean((sum % 10) === 0 ? sanitized : false)) { + return null; } - /** - * Validator that requires controls to have a value of phone. - */ - static phone(locale?: string): ValidatorFn { - const phones = { - 'zh-CN': /^(\+?0?86\-?)?((13\d|14[57]|15[^4,\D]|17[678]|18\d)\d{8}|170[059]\d{7})$/, - 'zh-TW': /^(\+?886\-?|0)?9\d{8}$/, - 'en-ZA': /^(\+?27|0)\d{9}$/, - 'en-AU': /^(\+?61|0)4\d{8}$/, - 'en-HK': /^(\+?852\-?)?[569]\d{3}\-?\d{4}$/, - 'fr-FR': /^(\+?33|0)[67]\d{8}$/, - 'de-DE': /^(\+?49|0)[1-9]\d{10}$/, - 'pt-PT': /^(\+351)?9[1236]\d{7}$/, - 'el-GR': /^(\+?30)?(69\d{8})$/, - 'en-GB': /^(\+?44|0)7\d{9}$/, - 'en-US': /^(\+?1)?[2-9]\d{2}[2-9](?!11)\d{6}$/, - 'en-ZM': /^(\+26)?09[567]\d{7}$/, - 'ru-RU': /^(\+?7|8)?9\d{9}$/, - 'nb-NO': /^(\+?47)?[49]\d{7}$/, - 'nn-NO': /^(\+?47)?[49]\d{7}$/, - 'vi-VN': /^(0|\+?84)?((1(2([0-9])|6([2-9])|88|99))|(9((?!5)[0-9])))([0-9]{7})$/, - 'en-NZ': /^(\+?64|0)2\d{7,9}$/ - }; - - return (control: AbstractControl): {[key: string]: any} => { - if (isPresent(Validators.required(control))) return null; - - let v: string = control.value; - let pattern = phones[locale] || phones['en-US']; - - return (new RegExp(pattern)).test(v) ? null : {'phone': true}; - }; - } + return {'creditCard': true}; + } - /** - * Validator that requires controls to have a value of uuid. - */ - static uuid(version?: string): ValidatorFn { - const uuid = { - '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i, - '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, - '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, - 'all': /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i - }; - - return (control: AbstractControl): {[key: string]: any} => { - if (isPresent(Validators.required(control))) return null; - - let v: string = control.value; - let pattern = uuid[version] || uuid.all; - - return (new RegExp(pattern)).test(v) ? null : {'uuid': true}; - }; - } + /** + * Validator that requires controls to have a value of JSON. + */ + static json(control: AbstractControl): {[key: string]: boolean} { + if (isPresent(Validators.required(control))) return null; - /** - * Validator that requires controls to have a value to equal another value. - */ - static equal(str: EqualValueType): ValidatorFn { - return (control: AbstractControl): {[key: string]: any} => { - if (isPresent(Validators.required(control))) return null; + let v: string = control.value; - let v: string = control.value; + try { + let obj = JSON.parse(v); - return str === v ? null : {equal: true}; - }; + if (Boolean(obj) && typeof obj === 'object') { + return null; + } + } catch (e) { } - - /** - * Validator that requires controls to have a value to equal another control. - */ - static equalTo(equalControl: AbstractControl): ValidatorFn { - return (control: AbstractControl): {[key: string]: any} => { - if (isPresent(Validators.required(control))) return null; - - let v: string = control.value; - - return equalControl.value === v ? null : {equalTo: true}; - }; + return {'json': true}; + } + + /** + * Validator that requires controls to have a value of base64. + */ + static base64(control: AbstractControl): {[key: string]: boolean} { + if (isPresent(Validators.required(control))) return null; + + let v: string = control.value; + return /^(?:[A-Z0-9+\/]{4})*(?:[A-Z0-9+\/]{2}==|[A-Z0-9+\/]{3}=|[A-Z0-9+\/]{4})$/i.test(v) ? null : {'base64': true}; + } + + /** + * Validator that requires controls to have a value of phone. + */ + static phone(locale?: string): ValidatorFn { + const phones = { + 'zh-CN': /^(\+?0?86\-?)?((13\d|14[57]|15[^4,\D]|17[678]|18\d)\d{8}|170[059]\d{7})$/, + 'zh-TW': /^(\+?886\-?|0)?9\d{8}$/, + 'en-ZA': /^(\+?27|0)\d{9}$/, + 'en-AU': /^(\+?61|0)4\d{8}$/, + 'en-HK': /^(\+?852\-?)?[569]\d{3}\-?\d{4}$/, + 'fr-FR': /^(\+?33|0)[67]\d{8}$/, + 'de-DE': /^(\+?49|0)[1-9]\d{10}$/, + 'pt-PT': /^(\+351)?9[1236]\d{7}$/, + 'el-GR': /^(\+?30)?(69\d{8})$/, + 'en-GB': /^(\+?44|0)7\d{9}$/, + 'en-US': /^(\+?1)?[2-9]\d{2}[2-9](?!11)\d{6}$/, + 'en-ZM': /^(\+26)?09[567]\d{7}$/, + 'ru-RU': /^(\+?7|8)?9\d{9}$/, + 'nb-NO': /^(\+?47)?[49]\d{7}$/, + 'nn-NO': /^(\+?47)?[49]\d{7}$/, + 'vi-VN': /^(0|\+?84)?((1(2([0-9])|6([2-9])|88|99))|(9((?!5)[0-9])))([0-9]{7})$/, + 'en-NZ': /^(\+?64|0)2\d{7,9}$/ + }; + + return (control: AbstractControl): {[key: string]: any} => { + if (isPresent(Validators.required(control))) return null; + + let v: string = control.value; + let pattern = phones[locale] || phones['en-US']; + + return (new RegExp(pattern)).test(v) ? null : {'phone': true}; + }; + } + + /** + * Validator that requires controls to have a value of uuid. + */ + static uuid(version?: string): ValidatorFn { + const uuid = { + '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i, + '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + 'all': /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i + }; + + return (control: AbstractControl): {[key: string]: any} => { + if (isPresent(Validators.required(control))) return null; + + let v: string = control.value; + let pattern = uuid[version] || uuid.all; + + return (new RegExp(pattern)).test(v) ? null : {'uuid': true}; + }; + } + + /** + * Validator that requires controls to have a value to equal another value. + */ + static equal(val: any): ValidatorFn { + return (control: AbstractControl): {[key: string]: any} => { + if (isPresent(Validators.required(control))) return null; + + let v: any = control.value; + + return val === v ? null : {equal: true}; + }; + } + + /** + * Validator that requires controls to have a value to equal another control. + */ + static equalTo(group: FormGroup): {[key: string]: boolean} { + let keys: string[] = Object.keys(group.controls); + let len: number = keys.length; + + if (!len) return null; + + let firstKey = keys[0]; + + for (let i = 1; i < len; i++) { + if (group.controls[firstKey].value !== group.controls[keys[i]].value) { + return {equalTo: true}; + } } + + return null; + } } \ No newline at end of file diff --git a/src/directives.ts b/src/directives.ts index a693779..82132b3 100644 --- a/src/directives.ts +++ b/src/directives.ts @@ -20,28 +20,28 @@ import { EqualToValidator } from './directives/equal-to'; const CUSTOM_FORM_DIRECTIVES = [ - RangeLengthValidator, - MinValidator, - MaxValidator, - RangeValidator, - DigitsValidator, - NumberValidator, - UrlValidator, - EmailValidator, - DateValidator, - DateISOValidator, - CreditCardValidator, - JSONValidator, - Base64Validator, - PhoneValidator, - UUIDValidator, - EqualValidator, - EqualToValidator + RangeLengthValidator, + MinValidator, + MaxValidator, + RangeValidator, + DigitsValidator, + NumberValidator, + UrlValidator, + EmailValidator, + DateValidator, + DateISOValidator, + CreditCardValidator, + JSONValidator, + Base64Validator, + PhoneValidator, + UUIDValidator, + EqualValidator, + EqualToValidator ]; @NgModule({ - declarations: [CUSTOM_FORM_DIRECTIVES], - exports: [CUSTOM_FORM_DIRECTIVES] + declarations: [CUSTOM_FORM_DIRECTIVES], + exports: [CUSTOM_FORM_DIRECTIVES] }) export class CustomFormsModule { } diff --git a/src/directives/base64.ts b/src/directives/base64.ts index f2f9360..84ed933 100644 --- a/src/directives/base64.ts +++ b/src/directives/base64.ts @@ -4,17 +4,17 @@ import { NG_VALIDATORS, Validator, AbstractControl } from '@angular/forms'; import { CustomValidators } from '../'; const BASE64_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => Base64Validator), - multi: true + provide: NG_VALIDATORS, + useExisting: forwardRef(() => Base64Validator), + multi: true }; @Directive({ - selector: '[base64][formControlName],[base64][formControl],[base64][ngModel]', - providers: [BASE64_VALIDATOR] + selector: '[base64][formControlName],[base64][formControl],[base64][ngModel]', + providers: [BASE64_VALIDATOR] }) export class Base64Validator implements Validator { - validate(c: AbstractControl): {[key: string]: any} { - return CustomValidators.base64(c); - } + validate(c: AbstractControl): {[key: string]: any} { + return CustomValidators.base64(c); + } } \ No newline at end of file diff --git a/src/directives/credit-card.ts b/src/directives/credit-card.ts index a0c17d7..3eb8b29 100644 --- a/src/directives/credit-card.ts +++ b/src/directives/credit-card.ts @@ -4,17 +4,17 @@ import { NG_VALIDATORS, Validator, AbstractControl } from '@angular/forms'; import { CustomValidators } from '../'; const CREDIT_CARD_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => CreditCardValidator), - multi: true + provide: NG_VALIDATORS, + useExisting: forwardRef(() => CreditCardValidator), + multi: true }; @Directive({ - selector: '[creditCard][formControlName],[creditCard][formControl],[creditCard][ngModel]', - providers: [CREDIT_CARD_VALIDATOR] + selector: '[creditCard][formControlName],[creditCard][formControl],[creditCard][ngModel]', + providers: [CREDIT_CARD_VALIDATOR] }) export class CreditCardValidator implements Validator { - validate(c: AbstractControl): {[key: string]: any} { - return CustomValidators.creditCard(c); - } + validate(c: AbstractControl): {[key: string]: any} { + return CustomValidators.creditCard(c); + } } \ No newline at end of file diff --git a/src/directives/date-iso.ts b/src/directives/date-iso.ts index e8d3a60..5b3df69 100644 --- a/src/directives/date-iso.ts +++ b/src/directives/date-iso.ts @@ -4,17 +4,17 @@ import { NG_VALIDATORS, Validator, AbstractControl } from '@angular/forms'; import { CustomValidators } from '../'; const DATE_ISO_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DateISOValidator), - multi: true + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DateISOValidator), + multi: true }; @Directive({ - selector: '[dateISO][formControlName],[dateISO][formControl],[dateISO][ngModel]', - providers: [DATE_ISO_VALIDATOR] + selector: '[dateISO][formControlName],[dateISO][formControl],[dateISO][ngModel]', + providers: [DATE_ISO_VALIDATOR] }) export class DateISOValidator implements Validator { - validate(c: AbstractControl): {[key: string]: any} { - return CustomValidators.dateISO(c); - } + validate(c: AbstractControl): {[key: string]: any} { + return CustomValidators.dateISO(c); + } } \ No newline at end of file diff --git a/src/directives/date.ts b/src/directives/date.ts index b11cf6b..d11cbca 100644 --- a/src/directives/date.ts +++ b/src/directives/date.ts @@ -4,17 +4,17 @@ import { NG_VALIDATORS, Validator, AbstractControl } from '@angular/forms'; import { CustomValidators } from '../'; const DATE_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DateValidator), - multi: true + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DateValidator), + multi: true }; @Directive({ - selector: '[date][formControlName],[date][formControl],[date][ngModel]', - providers: [DATE_VALIDATOR] + selector: '[date][formControlName],[date][formControl],[date][ngModel]', + providers: [DATE_VALIDATOR] }) export class DateValidator implements Validator { - validate(c: AbstractControl): {[key: string]: any} { - return CustomValidators.date(c); - } + validate(c: AbstractControl): {[key: string]: any} { + return CustomValidators.date(c); + } } \ No newline at end of file diff --git a/src/directives/digits.ts b/src/directives/digits.ts index a2efb02..65d6c54 100644 --- a/src/directives/digits.ts +++ b/src/directives/digits.ts @@ -4,17 +4,17 @@ import { NG_VALIDATORS, Validator, AbstractControl } from '@angular/forms'; import { CustomValidators } from '../'; const DIGITS_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => DigitsValidator), - multi: true + provide: NG_VALIDATORS, + useExisting: forwardRef(() => DigitsValidator), + multi: true }; @Directive({ - selector: '[digits][formControlName],[digits][formControl],[digits][ngModel]', - providers: [DIGITS_VALIDATOR] + selector: '[digits][formControlName],[digits][formControl],[digits][ngModel]', + providers: [DIGITS_VALIDATOR] }) export class DigitsValidator implements Validator { - validate(c: AbstractControl): {[key: string]: any} { - return CustomValidators.digits(c); - } + validate(c: AbstractControl): {[key: string]: any} { + return CustomValidators.digits(c); + } } diff --git a/src/directives/email.ts b/src/directives/email.ts index bc9762f..dea053f 100644 --- a/src/directives/email.ts +++ b/src/directives/email.ts @@ -4,17 +4,17 @@ import { NG_VALIDATORS, Validator, AbstractControl } from '@angular/forms'; import { CustomValidators } from '../'; const EMAIL_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => EmailValidator), - multi: true + provide: NG_VALIDATORS, + useExisting: forwardRef(() => EmailValidator), + multi: true }; @Directive({ - selector: '[email][formControlName],[email][formControl],[email][ngModel]', - providers: [EMAIL_VALIDATOR] + selector: '[email][formControlName],[email][formControl],[email][ngModel]', + providers: [EMAIL_VALIDATOR] }) export class EmailValidator implements Validator { - validate(c: AbstractControl): {[key: string]: any} { - return CustomValidators.email(c); - } + validate(c: AbstractControl): {[key: string]: any} { + return CustomValidators.email(c); + } } \ No newline at end of file diff --git a/src/directives/equal-to.ts b/src/directives/equal-to.ts index 55d4a88..c023689 100644 --- a/src/directives/equal-to.ts +++ b/src/directives/equal-to.ts @@ -1,28 +1,20 @@ -import { Directive, Input, forwardRef, OnInit } from '@angular/core'; -import { NG_VALIDATORS, Validator, ValidatorFn, AbstractControl } from '@angular/forms'; +import { Directive, forwardRef } from '@angular/core'; +import { NG_VALIDATORS, Validator, FormGroup, NgModelGroup } from '@angular/forms'; import { CustomValidators } from '../'; const EQUAL_TO_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => EqualToValidator), - multi: true + provide: NG_VALIDATORS, + useExisting: forwardRef(() => EqualToValidator), + multi: true }; @Directive({ - selector: '[equalTo][formControlName],[equalTo][formControl],[equalTo][ngModel]', - providers: [EQUAL_TO_VALIDATOR] + selector: '[equalTo][ngModelGroup]', + providers: [EQUAL_TO_VALIDATOR] }) -export class EqualToValidator implements Validator, OnInit { - @Input() equalTo: AbstractControl; - - private validator: ValidatorFn; - - ngOnInit() { - this.validator = CustomValidators.equalTo(this.equalTo); - } - - validate(c: AbstractControl): {[key: string]: any} { - return this.validator(c); - } +export class EqualToValidator implements Validator { + validate(c: FormGroup): {[key: string]: any} { + return CustomValidators.equalTo(c); + } } \ No newline at end of file diff --git a/src/directives/equal.ts b/src/directives/equal.ts index 957c102..4e74c92 100644 --- a/src/directives/equal.ts +++ b/src/directives/equal.ts @@ -2,7 +2,6 @@ import { Directive, Input, forwardRef, OnInit } from '@angular/core'; import { NG_VALIDATORS, Validator, ValidatorFn, AbstractControl } from '@angular/forms'; import { CustomValidators } from '../'; -import { EqualValueType } from '../custom-validators'; const EQUAL_VALIDATOR: any = { provide: NG_VALIDATORS, @@ -15,7 +14,7 @@ const EQUAL_VALIDATOR: any = { providers: [EQUAL_VALIDATOR] }) export class EqualValidator implements Validator, OnInit { - @Input() equal: EqualValueType; + @Input() equal: any; private validator: ValidatorFn; diff --git a/src/directives/json.ts b/src/directives/json.ts index b476d24..3de5ef6 100644 --- a/src/directives/json.ts +++ b/src/directives/json.ts @@ -4,17 +4,17 @@ import { NG_VALIDATORS, Validator, AbstractControl } from '@angular/forms'; import { CustomValidators } from '../'; const JSON_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => JSONValidator), - multi: true + provide: NG_VALIDATORS, + useExisting: forwardRef(() => JSONValidator), + multi: true }; @Directive({ - selector: '[json][formControlName],[json][formControl],[json][ngModel]', - providers: [JSON_VALIDATOR] + selector: '[json][formControlName],[json][formControl],[json][ngModel]', + providers: [JSON_VALIDATOR] }) export class JSONValidator implements Validator { - validate(c: AbstractControl): {[key: string]: any} { - return CustomValidators.json(c); - } + validate(c: AbstractControl): {[key: string]: any} { + return CustomValidators.json(c); + } } \ No newline at end of file diff --git a/src/directives/max.ts b/src/directives/max.ts index 0fcf3a9..14d0064 100644 --- a/src/directives/max.ts +++ b/src/directives/max.ts @@ -4,25 +4,25 @@ import { NG_VALIDATORS, Validator, ValidatorFn, AbstractControl } from '@angular import { CustomValidators } from '../'; const MAX_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MaxValidator), - multi: true + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MaxValidator), + multi: true }; @Directive({ - selector: '[max][formControlName],[max][formControl],[max][ngModel]', - providers: [MAX_VALIDATOR] + selector: '[max][formControlName],[max][formControl],[max][ngModel]', + providers: [MAX_VALIDATOR] }) export class MaxValidator implements Validator, OnInit { - @Input() max: number; + @Input() max: number; - private validator: ValidatorFn; + private validator: ValidatorFn; - ngOnInit() { - this.validator = CustomValidators.max(this.max); - } + ngOnInit() { + this.validator = CustomValidators.max(this.max); + } - validate(c: AbstractControl): {[key: string]: any} { - return this.validator(c); - } + validate(c: AbstractControl): {[key: string]: any} { + return this.validator(c); + } } diff --git a/src/directives/min.ts b/src/directives/min.ts index 60c6345..ef988c9 100644 --- a/src/directives/min.ts +++ b/src/directives/min.ts @@ -4,25 +4,25 @@ import { NG_VALIDATORS, Validator, ValidatorFn, AbstractControl } from '@angular import { CustomValidators } from '../'; const MIN_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MinValidator), - multi: true + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MinValidator), + multi: true }; @Directive({ - selector: '[min][formControlName],[min][formControl],[min][ngModel]', - providers: [MIN_VALIDATOR] + selector: '[min][formControlName],[min][formControl],[min][ngModel]', + providers: [MIN_VALIDATOR] }) export class MinValidator implements Validator, OnInit { - @Input() min: number; + @Input() min: number; - private validator: ValidatorFn; + private validator: ValidatorFn; - ngOnInit() { - this.validator = CustomValidators.min(this.min); - } + ngOnInit() { + this.validator = CustomValidators.min(this.min); + } - validate(c: AbstractControl): {[key: string]: any} { - return this.validator(c); - } + validate(c: AbstractControl): {[key: string]: any} { + return this.validator(c); + } } diff --git a/src/directives/number.ts b/src/directives/number.ts index 078d53c..7444ccd 100644 --- a/src/directives/number.ts +++ b/src/directives/number.ts @@ -4,17 +4,17 @@ import { NG_VALIDATORS, Validator, AbstractControl } from '@angular/forms'; import { CustomValidators } from '../'; const NUMBER_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => NumberValidator), - multi: true + provide: NG_VALIDATORS, + useExisting: forwardRef(() => NumberValidator), + multi: true }; @Directive({ - selector: '[number][formControlName],[number][formControl],[number][ngModel]', - providers: [NUMBER_VALIDATOR] + selector: '[number][formControlName],[number][formControl],[number][ngModel]', + providers: [NUMBER_VALIDATOR] }) export class NumberValidator implements Validator { - validate(c: AbstractControl): {[key: string]: any} { - return CustomValidators.number(c); - } + validate(c: AbstractControl): {[key: string]: any} { + return CustomValidators.number(c); + } } \ No newline at end of file diff --git a/src/directives/phone.ts b/src/directives/phone.ts index cf7553a..43be706 100644 --- a/src/directives/phone.ts +++ b/src/directives/phone.ts @@ -4,25 +4,25 @@ import { NG_VALIDATORS, Validator, ValidatorFn, AbstractControl } from '@angular import { CustomValidators } from '../'; const PHONE_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => PhoneValidator), - multi: true + provide: NG_VALIDATORS, + useExisting: forwardRef(() => PhoneValidator), + multi: true }; @Directive({ - selector: '[phone][formControlName],[phone][formControl],[phone][ngModel]', - providers: [PHONE_VALIDATOR] + selector: '[phone][formControlName],[phone][formControl],[phone][ngModel]', + providers: [PHONE_VALIDATOR] }) export class PhoneValidator implements Validator, OnInit { - @Input() phone: string; + @Input() phone: string; - private validator: ValidatorFn; + private validator: ValidatorFn; - ngOnInit() { - this.validator = CustomValidators.phone(this.phone); - } + ngOnInit() { + this.validator = CustomValidators.phone(this.phone); + } - validate(c: AbstractControl): {[key: string]: any} { - return this.validator(c); - } + validate(c: AbstractControl): {[key: string]: any} { + return this.validator(c); + } } diff --git a/src/directives/range-length.ts b/src/directives/range-length.ts index 91eaf78..5cc5e48 100644 --- a/src/directives/range-length.ts +++ b/src/directives/range-length.ts @@ -4,25 +4,25 @@ import { NG_VALIDATORS, Validator, ValidatorFn, AbstractControl } from '@angular import { CustomValidators } from '../'; const RANGE_LENGTH_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => RangeLengthValidator), - multi: true + provide: NG_VALIDATORS, + useExisting: forwardRef(() => RangeLengthValidator), + multi: true }; @Directive({ - selector: '[rangeLength][formControlName],[rangeLength][formControl],[rangeLength][ngModel]', - providers: [RANGE_LENGTH_VALIDATOR] + selector: '[rangeLength][formControlName],[rangeLength][formControl],[rangeLength][ngModel]', + providers: [RANGE_LENGTH_VALIDATOR] }) export class RangeLengthValidator implements Validator,OnInit { - @Input() rangeLength: [number]; + @Input() rangeLength: [number]; - private validator: ValidatorFn; + private validator: ValidatorFn; - ngOnInit() { - this.validator = CustomValidators.rangeLength(this.rangeLength); - } + ngOnInit() { + this.validator = CustomValidators.rangeLength(this.rangeLength); + } - validate(c: AbstractControl): {[key: string]: any} { - return this.validator(c); - } + validate(c: AbstractControl): {[key: string]: any} { + return this.validator(c); + } } diff --git a/src/directives/range.ts b/src/directives/range.ts index ff3662a..2e4b1dd 100644 --- a/src/directives/range.ts +++ b/src/directives/range.ts @@ -4,25 +4,25 @@ import { NG_VALIDATORS, Validator, ValidatorFn, AbstractControl } from '@angular import { CustomValidators } from '../'; const RANGE_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => RangeValidator), - multi: true + provide: NG_VALIDATORS, + useExisting: forwardRef(() => RangeValidator), + multi: true }; @Directive({ - selector: '[range][formControlName],[range][formControl],[range][ngModel]', - providers: [RANGE_VALIDATOR] + selector: '[range][formControlName],[range][formControl],[range][ngModel]', + providers: [RANGE_VALIDATOR] }) export class RangeValidator implements Validator, OnInit { - @Input() range: [number]; + @Input() range: [number]; - private validator: ValidatorFn; + private validator: ValidatorFn; - ngOnInit() { - this.validator = CustomValidators.range(this.range); - } + ngOnInit() { + this.validator = CustomValidators.range(this.range); + } - validate(c: AbstractControl): {[key: string]: any} { - return this.validator(c); - } + validate(c: AbstractControl): {[key: string]: any} { + return this.validator(c); + } } diff --git a/src/directives/url.ts b/src/directives/url.ts index bada7ed..779940b 100644 --- a/src/directives/url.ts +++ b/src/directives/url.ts @@ -4,17 +4,17 @@ import { NG_VALIDATORS, Validator, AbstractControl } from '@angular/forms'; import { CustomValidators } from '../'; const URL_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => UrlValidator), - multi: true + provide: NG_VALIDATORS, + useExisting: forwardRef(() => UrlValidator), + multi: true }; @Directive({ - selector: '[url][formControlName],[url][formControl],[url][ngModel]', - providers: [URL_VALIDATOR] + selector: '[url][formControlName],[url][formControl],[url][ngModel]', + providers: [URL_VALIDATOR] }) export class UrlValidator implements Validator { - validate(c: AbstractControl): {[key: string]: any} { - return CustomValidators.url(c); - } + validate(c: AbstractControl): {[key: string]: any} { + return CustomValidators.url(c); + } } \ No newline at end of file diff --git a/src/directives/uuid.ts b/src/directives/uuid.ts index 3391fc2..ed2e6ff 100644 --- a/src/directives/uuid.ts +++ b/src/directives/uuid.ts @@ -4,25 +4,25 @@ import { NG_VALIDATORS, Validator, ValidatorFn, AbstractControl } from '@angular import { CustomValidators } from '../'; const UUID_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => UUIDValidator), - multi: true + provide: NG_VALIDATORS, + useExisting: forwardRef(() => UUIDValidator), + multi: true }; @Directive({ - selector: '[uuid][formControlName],[uuid][formControl],[uuid][ngModel]', - providers: [UUID_VALIDATOR] + selector: '[uuid][formControlName],[uuid][formControl],[uuid][ngModel]', + providers: [UUID_VALIDATOR] }) export class UUIDValidator implements Validator, OnInit { - @Input() uuid; + @Input() uuid; - private validator: ValidatorFn; + private validator: ValidatorFn; - ngOnInit() { - this.validator = CustomValidators.uuid(this.uuid); - } + ngOnInit() { + this.validator = CustomValidators.uuid(this.uuid); + } - validate(c: AbstractControl): {[key: string]: any} { - return this.validator(c); - } + validate(c: AbstractControl): {[key: string]: any} { + return this.validator(c); + } } diff --git a/src/lang.ts b/src/lang.ts index 38528ba..140cb7a 100644 --- a/src/lang.ts +++ b/src/lang.ts @@ -1,7 +1,3 @@ export function isPresent(obj: any): boolean { - return obj !== undefined && obj !== null; -} - -export function isString(obj: any): obj is String { - return typeof obj === 'string'; + return obj !== undefined && obj !== null; } \ No newline at end of file diff --git a/src/specs/custom-validators.spec.ts b/src/specs/custom-validators.spec.ts index fc0feb9..ad809f5 100644 --- a/src/specs/custom-validators.spec.ts +++ b/src/specs/custom-validators.spec.ts @@ -3,257 +3,257 @@ import { FormControl, ValidatorFn } from '@angular/forms'; import { CustomValidators } from '../custom-validators'; describe('Custom Validators RangeLength [4,9],', () => { - let control: FormControl; - let validator: ValidatorFn; - - beforeEach(() => { - validator = CustomValidators.rangeLength([4, 9]); - }); - - it('"abc" should equal to "{rangeLength: true}"', () => { - control = new FormControl('abc'); - expect(validator(control)).toEqual({rangeLength: true}); - }); - - it('"abcd" should equal to "null"', () => { - control = new FormControl('abcd'); - expect(validator(control)).toBeNull(); - }); - - it('"abcdefghi" should equal to "null"', () => { - control = new FormControl('abcdefghi'); - expect(validator(control)).toBeNull(); - }); - - it('"abcdefghij" should equal to "{rangeLength: true}"', () => { - control = new FormControl('abcdefghij'); - expect(validator(control)).toEqual({rangeLength: true}); - }); + let control: FormControl; + let validator: ValidatorFn; + + beforeEach(() => { + validator = CustomValidators.rangeLength([4, 9]); + }); + + it('"abc" should equal to "{rangeLength: true}"', () => { + control = new FormControl('abc'); + expect(validator(control)).toEqual({rangeLength: true}); + }); + + it('"abcd" should equal to "null"', () => { + control = new FormControl('abcd'); + expect(validator(control)).toBeNull(); + }); + + it('"abcdefghi" should equal to "null"', () => { + control = new FormControl('abcdefghi'); + expect(validator(control)).toBeNull(); + }); + + it('"abcdefghij" should equal to "{rangeLength: true}"', () => { + control = new FormControl('abcdefghij'); + expect(validator(control)).toEqual({rangeLength: true}); + }); }); describe('Custom Validators Min 10,', () => { - let control: FormControl; - let validator: ValidatorFn; - - beforeEach(() => { - validator = CustomValidators.min(10); - }); - - it('"9" should equal to "{min: true}"', () => { - control = new FormControl(9); - expect(validator(control)).toEqual({min: true}); - }); - - it('"10" should equal to "null"', () => { - control = new FormControl(10); - expect(validator(control)).toBeNull() - }); - - it('"11" should equal to "null"', () => { - control = new FormControl(11); - expect(validator(control)).toBeNull() - }); + let control: FormControl; + let validator: ValidatorFn; + + beforeEach(() => { + validator = CustomValidators.min(10); + }); + + it('"9" should equal to "{min: true}"', () => { + control = new FormControl(9); + expect(validator(control)).toEqual({min: true}); + }); + + it('"10" should equal to "null"', () => { + control = new FormControl(10); + expect(validator(control)).toBeNull() + }); + + it('"11" should equal to "null"', () => { + control = new FormControl(11); + expect(validator(control)).toBeNull() + }); }); describe('Custom Validators Max 20,', () => { - let control: FormControl; - let validator: ValidatorFn; - - beforeEach(() => { - validator = CustomValidators.max(20); - }); - - it('"19" should equal to "null"', () => { - control = new FormControl(19); - expect(validator(control)).toBeNull() - }); - - it('"20" should equal to "null"', () => { - control = new FormControl(20); - expect(validator(control)).toBeNull() - }); - - it('"21" should equal to "{max: true}"', () => { - control = new FormControl(21); - expect(validator(control)).toEqual({max: true}); - }); + let control: FormControl; + let validator: ValidatorFn; + + beforeEach(() => { + validator = CustomValidators.max(20); + }); + + it('"19" should equal to "null"', () => { + control = new FormControl(19); + expect(validator(control)).toBeNull() + }); + + it('"20" should equal to "null"', () => { + control = new FormControl(20); + expect(validator(control)).toBeNull() + }); + + it('"21" should equal to "{max: true}"', () => { + control = new FormControl(21); + expect(validator(control)).toEqual({max: true}); + }); }); describe('Custom Validators Range [4,9],', () => { - let control: FormControl; - let validator: ValidatorFn; - - beforeEach(() => { - validator = CustomValidators.range([4, 9]); - }); - - it('"3" should equal to "{range: true}"', () => { - control = new FormControl(3); - expect(validator(control)).toEqual({range: true}); - }); - - it('"4" should equal to "null"', () => { - control = new FormControl(4); - expect(validator(control)).toBeNull(); - }); - - it('"9" should equal to "null"', () => { - control = new FormControl(9); - expect(validator(control)).toBeNull(); - }); - - it('"10" should equal to "{range: true}"', () => { - control = new FormControl(10); - expect(validator(control)).toEqual({range: true}); - }); + let control: FormControl; + let validator: ValidatorFn; + + beforeEach(() => { + validator = CustomValidators.range([4, 9]); + }); + + it('"3" should equal to "{range: true}"', () => { + control = new FormControl(3); + expect(validator(control)).toEqual({range: true}); + }); + + it('"4" should equal to "null"', () => { + control = new FormControl(4); + expect(validator(control)).toBeNull(); + }); + + it('"9" should equal to "null"', () => { + control = new FormControl(9); + expect(validator(control)).toBeNull(); + }); + + it('"10" should equal to "{range: true}"', () => { + control = new FormControl(10); + expect(validator(control)).toEqual({range: true}); + }); }); describe('Custom Validators Digits,', () => { - let control: FormControl; - let validator: ValidatorFn; - - beforeEach(() => { - validator = CustomValidators.digits; - }); - - it('"23" should equal to "null"', () => { - control = new FormControl(23); - expect(validator(control)).toBeNull() - }); - - it('"23a" should equal to "{digits: true}"', () => { - control = new FormControl('23a'); - expect(validator(control)).toEqual({digits: true}); - }); + let control: FormControl; + let validator: ValidatorFn; + + beforeEach(() => { + validator = CustomValidators.digits; + }); + + it('"23" should equal to "null"', () => { + control = new FormControl(23); + expect(validator(control)).toBeNull() + }); + + it('"23a" should equal to "{digits: true}"', () => { + control = new FormControl('23a'); + expect(validator(control)).toEqual({digits: true}); + }); }); describe('Custom Validators Number,', () => { - let control: FormControl; - let validator: ValidatorFn; - - beforeEach(() => { - validator = CustomValidators.number; - }); - - it('"23" should equal to "null"', () => { - control = new FormControl('23'); - expect(validator(control)).toBeNull() - }); - - it('"23.3" should equal to "null"', () => { - control = new FormControl('23.3'); - expect(validator(control)).toBeNull() - }); - - it('"23a" should equal to "{number: true}"', () => { - control = new FormControl('23a'); - expect(validator(control)).toEqual({number: true}); - }); - - it('"23." should equal to "{number: true}"', () => { - control = new FormControl('23.'); - expect(validator(control)).toEqual({number: true}); - }); + let control: FormControl; + let validator: ValidatorFn; + + beforeEach(() => { + validator = CustomValidators.number; + }); + + it('"23" should equal to "null"', () => { + control = new FormControl('23'); + expect(validator(control)).toBeNull() + }); + + it('"23.3" should equal to "null"', () => { + control = new FormControl('23.3'); + expect(validator(control)).toBeNull() + }); + + it('"23a" should equal to "{number: true}"', () => { + control = new FormControl('23a'); + expect(validator(control)).toEqual({number: true}); + }); + + it('"23." should equal to "{number: true}"', () => { + control = new FormControl('23.'); + expect(validator(control)).toEqual({number: true}); + }); }); describe('Custom Validators Url,', () => { - let control: FormControl; - let validator: ValidatorFn; - - beforeEach(() => { - validator = CustomValidators.url; - }); - - it('"http://www.test.com" should equal to "null"', () => { - control = new FormControl('http://www.test.com'); - expect(validator(control)).toBeNull() - }); - - it('"https://www.test.com" should equal to "null"', () => { - control = new FormControl('https://www.test.com'); - expect(validator(control)).toBeNull() - }); - - it('"23a" should equal to "{url: true}"', () => { - control = new FormControl('23a'); - expect(validator(control)).toEqual({url: true}); - }); + let control: FormControl; + let validator: ValidatorFn; + + beforeEach(() => { + validator = CustomValidators.url; + }); + + it('"http://www.test.com" should equal to "null"', () => { + control = new FormControl('http://www.test.com'); + expect(validator(control)).toBeNull() + }); + + it('"https://www.test.com" should equal to "null"', () => { + control = new FormControl('https://www.test.com'); + expect(validator(control)).toBeNull() + }); + + it('"23a" should equal to "{url: true}"', () => { + control = new FormControl('23a'); + expect(validator(control)).toEqual({url: true}); + }); }); describe('Custom Validators Email,', () => { - let control: FormControl; - let validator: ValidatorFn; - - beforeEach(() => { - validator = CustomValidators.email; - }); - - it('"tester@gmail.com" should equal to "null"', () => { - control = new FormControl('tester@gmail.com'); - expect(validator(control)).toBeNull() - }); - - it('"testergmail" should equal to "{email: true}"', () => { - control = new FormControl('testergmail'); - expect(validator(control)).toEqual({email: true}); - }); + let control: FormControl; + let validator: ValidatorFn; + + beforeEach(() => { + validator = CustomValidators.email; + }); + + it('"tester@gmail.com" should equal to "null"', () => { + control = new FormControl('tester@gmail.com'); + expect(validator(control)).toBeNull() + }); + + it('"testergmail" should equal to "{email: true}"', () => { + control = new FormControl('testergmail'); + expect(validator(control)).toEqual({email: true}); + }); }); describe('Custom Validators Equal (string),', () => { - let control: FormControl; - let validator: ValidatorFn; - - beforeEach(() => { - validator = CustomValidators.equal('xxx'); - }); - - it('"xxx" should equal to "null"', () => { - control = new FormControl('xxx'); - expect(validator(control)).toBeNull() - }); - - it('"yyy" should equal to "{equal: true}"', () => { - control = new FormControl('yyy'); - expect(validator(control)).toEqual({equal: true}); - }); + let control: FormControl; + let validator: ValidatorFn; + + beforeEach(() => { + validator = CustomValidators.equal('xxx'); + }); + + it('"xxx" should equal to "null"', () => { + control = new FormControl('xxx'); + expect(validator(control)).toBeNull() + }); + + it('"yyy" should equal to "{equal: true}"', () => { + control = new FormControl('yyy'); + expect(validator(control)).toEqual({equal: true}); + }); }); describe('Custom Validators Equal (boolean),', () => { - let control: FormControl; - let validator: ValidatorFn; - - beforeEach(() => { - validator = CustomValidators.equal(true); - }); - - it('"xxx" should equal to "null"', () => { - control = new FormControl(true); - expect(validator(control)).toBeNull() - }); - - it('"yyy" should equal to "{equal: true}"', () => { - control = new FormControl(false); - expect(validator(control)).toEqual({equal: true}); - }); + let control: FormControl; + let validator: ValidatorFn; + + beforeEach(() => { + validator = CustomValidators.equal(true); + }); + + it('"xxx" should equal to "null"', () => { + control = new FormControl(true); + expect(validator(control)).toBeNull() + }); + + it('"yyy" should equal to "{equal: true}"', () => { + control = new FormControl(false); + expect(validator(control)).toEqual({equal: true}); + }); }); describe('Custom Validators EqualTo,', () => { - let equalControl: FormControl; - let control: FormControl; - let validator: ValidatorFn; - - beforeEach(() => { - equalControl = new FormControl('xxx'); - validator = CustomValidators.equalTo(equalControl); - }); - - it('"xxx" should equal to "null"', () => { - control = new FormControl('xxx'); - expect(validator(control)).toBeNull() - }); - - it('"yyy" should equal to "{equalTo: true}"', () => { - control = new FormControl('yyy'); - expect(validator(control)).toEqual({equalTo: true}); - }); + let equalControl: FormControl; + let control: FormControl; + let validator: ValidatorFn; + + beforeEach(() => { + equalControl = new FormControl('xxx'); + validator = CustomValidators.equalTo(equalControl); + }); + + it('"xxx" should equal to "null"', () => { + control = new FormControl('xxx'); + expect(validator(control)).toBeNull() + }); + + it('"yyy" should equal to "{equalTo: true}"', () => { + control = new FormControl('yyy'); + expect(validator(control)).toEqual({equalTo: true}); + }); }); \ No newline at end of file