Skip to content

Commit 8820a24

Browse files
authored
Merge pull request #49 from Lemoncode/issue#48_support_field_validation_constraint
Issue#48 support field validation constraint
2 parents bdec257 + 151d8da commit 8820a24

37 files changed

+1135
-807
lines changed

lib/lcformvalidation.d.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ export class FormValidationResult {
1111
formGlobalErrors: Array<FieldValidationResult>;
1212
}
1313

14+
export interface ValidationEventsFilter {
15+
[key: string]: boolean;
16+
}
17+
1418
interface FormValidation {
15-
validateField(vm: any, key: string, value: any, filter?: any): Promise<FieldValidationResult>;
19+
validateField(vm: any, key: string, value: any, eventsFilter?: ValidationEventsFilter): Promise<FieldValidationResult>;
1620
validateForm(vm: any): Promise<FormValidationResult>;
1721
isValidationInProgress(): boolean;
1822
isFormDirty(): boolean;
1923
isFormPristine(): boolean;
20-
addFieldValidation(key: string, validation: (value: string, vm: any) => FieldValidationResult, filter?: any): FormValidation;
21-
addFieldValidationAsync(key: string, validation: (value: string, vm: any) => Promise<FieldValidationResult>, filter?: any): FormValidation;
2224
}
2325

2426
export type ValidationResult = FieldValidationResult | Promise<FieldValidationResult>;
@@ -27,8 +29,19 @@ export interface FormValidationFunction {
2729
(vm: any): ValidationResult;
2830
}
2931

30-
export interface ValidationConstraints extends Object {
32+
export interface FieldValidationFunction {
33+
(value: any, vm: any, customParams: any): ValidationResult;
34+
}
35+
36+
export interface FieldValidationConstraint{
37+
validator: FieldValidationFunction;
38+
eventFilters?: ValidationEventsFilter;
39+
customParams?: any;
40+
}
41+
42+
export interface ValidationConstraints{
3143
global?: FormValidationFunction[];
44+
fields?: { [key: string]: FieldValidationConstraint[] }
3245
}
3346

34-
export function createFormValidation(validationCredentials: ValidationConstraints): FormValidation;
47+
export function createFormValidation(validationCredentials: ValidationConstraints): FormValidation;

lib/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"main": "dist/lc-form-validation.js",
66
"scripts": {
77
"test": "karma start --browsers PhantomJS --single-run",
8-
"test:watch": "karma start --browsers PhantomJS",
8+
"test:watch": "karma start",
99
"clean": "rimraf dist ReadmeResources",
1010
"build:prod": "cross-env NODE_ENV=production webpack --output-filename dist/lc-form-validation.min.js",
1111
"build:dev": "cross-env NODE_ENV=development webpack --output-filename dist/lc-form-validation.js",
@@ -31,7 +31,7 @@
3131
"devDependencies": {
3232
"@types/chai": "^3.4.35",
3333
"@types/chai-as-promised": "^0.0.30",
34-
"@types/core-js": "^0.9.34",
34+
"@types/core-js": "0.9.36",
3535
"@types/karma-chai-sinon": "^0.1.5",
3636
"@types/mocha": "^2.2.39",
3737
"@types/sinon": "^1.16.31",

lib/src/baseFormValidation.ts

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,79 @@
11
import { ValidationEngine } from './validationEngine';
22
import {
33
ValidationConstraints,
4+
FieldValidationFunction,
45
FormValidationFunction,
56
FieldValidationResult,
67
FormValidationResult,
8+
FieldValidationConstraint,
9+
ValidationEventsFilter,
710
} from './entities';
811
import { consts } from './consts';
912

1013
interface FormValidation {
11-
validateField(vm: any, key: string, value: any, filter?: any): Promise<FieldValidationResult>;
14+
validateField(vm: any, key: string, value: any, eventsFilter?: any): Promise<FieldValidationResult>;
1215
validateForm(vm: any): Promise<FormValidationResult>;
1316
isValidationInProgress(): boolean;
1417
isFormDirty(): boolean;
1518
isFormPristine(): boolean;
16-
addFieldValidation(key: string, validation: (value: string, vm: any) => FieldValidationResult, filter?: any): FormValidation;
17-
addFieldValidationAsync(key: string, validation: (value: string, vm: any) => Promise<FieldValidationResult>, filter?: any): FormValidation;
1819
}
1920

2021
export class BaseFormValidation implements FormValidation {
2122
private validationEngine: ValidationEngine;
23+
2224
constructor(validationConstraints: ValidationConstraints) {
2325
this.validationEngine = new ValidationEngine();
2426
this.parseValidationConstraints(validationConstraints);
2527
}
2628

2729
private parseValidationConstraints(validationConstraints: ValidationConstraints) {
2830
if (validationConstraints && typeof validationConstraints === 'object') {
29-
if (validationConstraints.global && validationConstraints.global instanceof Array) {
30-
this.addFormValidationFunctions(validationConstraints.global);
31+
const { global, fields } = validationConstraints;
32+
if (global && global instanceof Array) {
33+
this.parseFormValidations(global);
34+
}
35+
if (fields && typeof fields === 'object') {
36+
this.parseAllFieldsValidations(fields);
3137
}
3238
}
3339
}
3440

35-
private addFormValidationFunctions(validationFunctions: FormValidationFunction[]) {
41+
private parseFormValidations(validationFunctions: FormValidationFunction[]) {
3642
validationFunctions.forEach((validationFunction: FormValidationFunction) => {
3743
if (typeof validationFunction === 'function') {
3844
this.validationEngine.addFormValidation(validationFunction);
3945
}
4046
});
4147
}
4248

43-
validateField(vm: any, key: string, value: any, filter?: any): Promise<FieldValidationResult> {
44-
return this.validationEngine.validateSingleField(vm, key, value, filter);
49+
private parseAllFieldsValidations(fields: { [key: string]: FieldValidationConstraint[] }) {
50+
for (let field in fields) {
51+
this.parseFieldValidations(field, fields[field]);
52+
}
53+
}
54+
55+
private parseFieldValidations(constraint: string, fieldValidationConstraints: FieldValidationConstraint[]) {
56+
if (fieldValidationConstraints instanceof Array) {
57+
fieldValidationConstraints.forEach((fieldValidationConstraint) => {
58+
if (fieldValidationConstraint && typeof fieldValidationConstraint === 'object') {
59+
this.addFieldValidation(constraint, fieldValidationConstraint);
60+
}
61+
});
62+
}
63+
}
64+
65+
private addFieldValidation(field: string, validationConstraint: FieldValidationConstraint): FormValidation {
66+
this.validationEngine.addFieldValidation(
67+
field,
68+
validationConstraint.validator,
69+
validationConstraint.eventsFilter,
70+
validationConstraint.customParams
71+
);
72+
return this;
73+
}
74+
75+
validateField(vm: any, key: string, value: any, eventsFilter?: ValidationEventsFilter): Promise<FieldValidationResult> {
76+
return this.validationEngine.triggerFieldValidation(vm, key, value, eventsFilter);
4577
}
4678

4779
validateForm(vm: any): Promise<FormValidationResult> {
@@ -59,18 +91,8 @@ export class BaseFormValidation implements FormValidation {
5991
isFormPristine(): boolean {
6092
return this.validationEngine.isFormPristine();
6193
}
62-
63-
addFieldValidation(key: string, validationFunction: (value: string, vm: any) => FieldValidationResult): FormValidation {
64-
this.validationEngine.addFieldValidation(key, validationFunction);
65-
return this;
66-
}
67-
68-
addFieldValidationAsync(key: string, validationFunction: (value: string, vm: any) => Promise<FieldValidationResult>): FormValidation {
69-
this.validationEngine.addFieldValidationAsync(key, validationFunction);
70-
return this;
71-
}
7294
}
7395

7496
export function createFormValidation(validationConstraints: ValidationConstraints): FormValidation {
7597
return new BaseFormValidation(validationConstraints);
76-
}
98+
}

lib/src/entities.ts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
export interface ValidationEventsFilter {
2+
[key: string]: boolean;
3+
}
4+
15
export class FieldValidation {
2-
public validationFn: (value, vm) => Promise<FieldValidationResult>;
3-
public filter: any;
6+
validationFn: (value, vm, customParams) => Promise<FieldValidationResult>;
7+
eventsFilter: ValidationEventsFilter;
8+
customParams: any;
49
}
510

611
export class FieldValidationResult {
@@ -19,8 +24,8 @@ export class FieldValidationResult {
1924

2025
export class FormValidationResult {
2126
succeeded: boolean;
22-
fieldErrors: Array<FieldValidationResult>;
23-
formGlobalErrors: Array<FieldValidationResult>;
27+
fieldErrors: FieldValidationResult[];
28+
formGlobalErrors: FieldValidationResult[];
2429

2530
constructor() {
2631
this.succeeded = false;
@@ -34,6 +39,21 @@ export interface FormValidationFunction {
3439
(vm: any): ValidationResult;
3540
}
3641

37-
export interface ValidationConstraints extends Object {
42+
export interface FieldValidationFunction {
43+
(value: any, vm: any, customParams: any): Promise<FieldValidationResult> |ValidationResult;
44+
}
45+
46+
export interface AsyncFieldValidationFunction {
47+
(value: any, vm: any, customParams: any): Promise<FieldValidationResult>;
48+
}
49+
50+
export interface FieldValidationConstraint {
51+
validator: FieldValidationFunction;
52+
eventsFilter?: ValidationEventsFilter;
53+
customParams?: any;
54+
}
55+
56+
export interface ValidationConstraints {
3857
global?: FormValidationFunction[];
58+
fields?: { [key: string]: FieldValidationConstraint[] };
3959
}

lib/src/entitiesMapper.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

lib/src/fieldValidationEventFilter.ts

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,25 @@
1-
import { FieldValidation } from './entities';
1+
import { FieldValidation, ValidationEventsFilter } from './entities';
22

33
class FieldValidationEventFilter {
44

5-
public filter(fieldValidations: Array<FieldValidation>, filter: any): Array<FieldValidation> {
6-
let result = new Array<FieldValidation>();
5+
public filter(fieldValidations: FieldValidation[], eventsFilter: ValidationEventsFilter): FieldValidation[] {
6+
let result: FieldValidation[] = [];
77

8-
if (filter) {
9-
result = fieldValidations.filter((element) => {
10-
return this.matchFilterOr(element, filter)
11-
});
8+
if (eventsFilter) {
9+
result = fieldValidations.filter((fieldValidation) =>
10+
this.hasAnyFilter(fieldValidation, eventsFilter)
11+
);
1212
} else {
1313
result = fieldValidations;
1414
}
1515

1616
return result;
1717
}
1818

19-
private matchFilterOr(itemFilter, globalFilter) {
20-
let result: boolean = false;
21-
22-
for (var property in globalFilter) {
23-
if (this.propertyMatched(itemFilter, property, globalFilter)) {
24-
result = true;
25-
break;
26-
}
27-
}
28-
29-
return result;
30-
}
31-
32-
private propertyMatched(item: any, property: any, globalFilter: any): boolean {
33-
return (globalFilter.hasOwnProperty(property) &&
34-
globalFilter[property] == item.filter[property]);
19+
private hasAnyFilter(fieldValidation: FieldValidation, eventsFilter: ValidationEventsFilter) {
20+
return Object.keys(eventsFilter).some(filter =>
21+
eventsFilter[filter] === fieldValidation.eventsFilter[filter]
22+
);
3523
}
3624
}
3725

0 commit comments

Comments
 (0)