@websolutespa/bom-mixer-forms 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +63 -46
- package/dist/index.d.ts +63 -49
- package/dist/index.js +49 -24
- package/dist/index.mjs +49 -23
- package/package.json +2 -2
- package/src/forms/form-abstract-collection.ts +7 -7
- package/src/forms/form-abstract.ts +10 -10
- package/src/forms/form-array.ts +3 -3
- package/src/forms/form-control.ts +3 -3
- package/src/forms/form-group.ts +2 -2
- package/src/forms/types.ts +31 -11
- package/src/forms/utils.ts +2 -23
- package/src/forms/validators/email.validator.ts +3 -2
- package/src/forms/validators/match.validator.ts +2 -2
- package/src/forms/validators/max-length.validator.ts +7 -3
- package/src/forms/validators/max.validator.ts +1 -1
- package/src/forms/validators/min-length.validator.ts +7 -3
- package/src/forms/validators/min.validator.ts +1 -1
- package/src/forms/validators/pattern.validator.ts +7 -3
- package/src/forms/validators/required-if.validator.ts +9 -4
- package/src/forms/validators/required.validator.ts +6 -1
- package/src/hooks/useFormBuilder/useFormBuilder.ts +8 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,46 +1,63 @@
|
|
|
1
|
-
# @websolutespa/bom-mixer-forms
|
|
2
|
-
|
|
3
|
-
## 0.3.
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
- Updated dependencies
|
|
9
|
-
- @websolutespa/bom-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
1
|
+
# @websolutespa/bom-mixer-forms
|
|
2
|
+
|
|
3
|
+
## 0.3.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Modified: validators, useFormBuilder
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @websolutespa/bom-core@1.7.9
|
|
10
|
+
|
|
11
|
+
## 0.3.2
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Fixing: downgrading eslint to v8.56.0
|
|
16
|
+
- Updated dependencies
|
|
17
|
+
- @websolutespa/bom-mixer-hooks@1.7.4
|
|
18
|
+
- @websolutespa/bom-core@1.7.8
|
|
19
|
+
|
|
20
|
+
## 0.3.1
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- Updating: dependencies
|
|
25
|
+
- Updated dependencies
|
|
26
|
+
- @websolutespa/bom-mixer-hooks@1.7.2
|
|
27
|
+
- @websolutespa/bom-core@1.7.3
|
|
28
|
+
|
|
29
|
+
## 0.3.0
|
|
30
|
+
|
|
31
|
+
### Minor Changes
|
|
32
|
+
|
|
33
|
+
- Updating: next 13.
|
|
34
|
+
|
|
35
|
+
## 0.2.2
|
|
36
|
+
|
|
37
|
+
### Patch Changes
|
|
38
|
+
|
|
39
|
+
- Removed: unnecessary method deepCopy.
|
|
40
|
+
|
|
41
|
+
## 0.2.1
|
|
42
|
+
|
|
43
|
+
### Patch Changes
|
|
44
|
+
|
|
45
|
+
- Added: source files.
|
|
46
|
+
|
|
47
|
+
## 0.2.0
|
|
48
|
+
|
|
49
|
+
### Minor Changes
|
|
50
|
+
|
|
51
|
+
- Added: splat routes.
|
|
52
|
+
|
|
53
|
+
## 0.1.0
|
|
54
|
+
|
|
55
|
+
### Minor Changes
|
|
56
|
+
|
|
57
|
+
- Added: @websolutespa/bom-core.
|
|
58
|
+
|
|
59
|
+
## 0.0.2
|
|
60
|
+
|
|
61
|
+
### Patch Changes
|
|
62
|
+
|
|
63
|
+
- Added: first release.
|
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ declare class FormAbstractCollection<T extends FormControls> extends FormAbstrac
|
|
|
16
16
|
constructor(controls: T, validators?: (FormValidator | FormValidator[]));
|
|
17
17
|
initControl_(controlOrValue: FormAbstract | any, key: any): FormAbstract;
|
|
18
18
|
protected setInitialOptions(options?: FormOptions): void;
|
|
19
|
-
protected checkAsyncPropState_(key:
|
|
19
|
+
protected checkAsyncPropState_(key: keyof FormFlags, option?: FormActivator, root?: FormCollection): Promise<boolean>;
|
|
20
20
|
updateState_(): void;
|
|
21
21
|
revalidate_(): Promise<void>;
|
|
22
22
|
protected validate_(root?: FormCollection): Promise<void>;
|
|
@@ -43,10 +43,10 @@ declare class FormAbstractCollection<T extends FormControls> extends FormAbstrac
|
|
|
43
43
|
set submitted(submitted: boolean);
|
|
44
44
|
set touched(touched: boolean);
|
|
45
45
|
get value(): {
|
|
46
|
-
[key: string]:
|
|
46
|
+
[key: string]: FormValue;
|
|
47
47
|
};
|
|
48
48
|
set value(value: {
|
|
49
|
-
[key: string]:
|
|
49
|
+
[key: string]: FormValue;
|
|
50
50
|
});
|
|
51
51
|
get errors(): {
|
|
52
52
|
[key: string]: any;
|
|
@@ -60,7 +60,7 @@ declare class FormArray extends FormAbstractCollection<FormAbstract[]> {
|
|
|
60
60
|
constructor(controls?: FormAbstract[], validators?: FormValidator | FormValidator[], initialOptions?: FormOptions);
|
|
61
61
|
forEach_(callback: (control: FormAbstract, key: number) => any): void;
|
|
62
62
|
map_(): FormAbstract[];
|
|
63
|
-
get value():
|
|
63
|
+
get value(): FormValue[];
|
|
64
64
|
get length(): number;
|
|
65
65
|
protected init(control: FormAbstract, key: number): void;
|
|
66
66
|
set(control: FormAbstract, key: number): void;
|
|
@@ -74,9 +74,9 @@ declare class FormArray extends FormAbstractCollection<FormAbstract[]> {
|
|
|
74
74
|
declare function formArray(controls?: FormAbstract[], validators?: FormValidator | FormValidator[]): FormArray;
|
|
75
75
|
|
|
76
76
|
declare class FormControl extends FormAbstract {
|
|
77
|
-
constructor(value?:
|
|
77
|
+
constructor(value?: FormValue, validators?: FormValidator | FormValidator[], initialOptions?: FormOptions);
|
|
78
78
|
}
|
|
79
|
-
declare function formControl(value?:
|
|
79
|
+
declare function formControl(value?: FormValue, validators?: FormValidator | FormValidator[]): FormControl;
|
|
80
80
|
|
|
81
81
|
declare class FormGroup extends FormAbstractCollection<{
|
|
82
82
|
[key: string]: FormAbstract;
|
|
@@ -86,9 +86,14 @@ declare class FormGroup extends FormAbstractCollection<{
|
|
|
86
86
|
}, validators?: FormValidator | FormValidator[], initialOptions?: FormOptions);
|
|
87
87
|
}
|
|
88
88
|
declare function formGroup(controls?: {
|
|
89
|
-
[key: string]: FormAbstract |
|
|
89
|
+
[key: string]: FormAbstract | FormValue;
|
|
90
90
|
}, validators?: FormValidator | FormValidator[]): FormGroup;
|
|
91
91
|
|
|
92
|
+
type FormValue = any;
|
|
93
|
+
type FormValueGroup = {
|
|
94
|
+
[key: string]: FormValue;
|
|
95
|
+
};
|
|
96
|
+
type FormValueArray = FormValue[];
|
|
92
97
|
type IControlParam = {
|
|
93
98
|
uid: number;
|
|
94
99
|
control: FormControl;
|
|
@@ -101,7 +106,7 @@ type FormOptions = {
|
|
|
101
106
|
schema?: ControlType;
|
|
102
107
|
name?: string;
|
|
103
108
|
label?: string;
|
|
104
|
-
value?:
|
|
109
|
+
value?: FormValue;
|
|
105
110
|
placeholder?: string;
|
|
106
111
|
required?: FormActivator;
|
|
107
112
|
hidden?: FormActivator;
|
|
@@ -116,21 +121,34 @@ type ValidationError = {
|
|
|
116
121
|
[key: string]: any;
|
|
117
122
|
};
|
|
118
123
|
type FormControls = {
|
|
119
|
-
[key: string]: FormAbstract;
|
|
124
|
+
[key: string]: FormAbstract | FormValue;
|
|
120
125
|
} | FormAbstract[];
|
|
121
126
|
type FormCollection = FormAbstractCollection<FormControls>;
|
|
122
|
-
type FormActivator = boolean | ((value:
|
|
123
|
-
type FormValidator = (value:
|
|
124
|
-
type FormAsyncValidator = (value:
|
|
127
|
+
type FormActivator = boolean | ((value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormCollection) => boolean | Promise<boolean>);
|
|
128
|
+
type FormValidator = (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormCollection) => null | ValidationError;
|
|
129
|
+
type FormAsyncValidator = (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormCollection) => Promise<null | ValidationError>;
|
|
125
130
|
type FormFlags = {
|
|
126
|
-
|
|
131
|
+
invalid: boolean;
|
|
132
|
+
disabled: boolean;
|
|
133
|
+
hidden: boolean;
|
|
134
|
+
readonly: boolean;
|
|
135
|
+
dirty: boolean;
|
|
136
|
+
touched: boolean;
|
|
137
|
+
submitted: boolean;
|
|
138
|
+
valid: boolean;
|
|
139
|
+
enabled: boolean;
|
|
140
|
+
visible: boolean;
|
|
141
|
+
writeable: boolean;
|
|
142
|
+
pristine: boolean;
|
|
143
|
+
untouched: boolean;
|
|
144
|
+
unsubmitted: boolean;
|
|
127
145
|
};
|
|
128
146
|
type FormErrors = {
|
|
129
147
|
[key: string]: any;
|
|
130
148
|
};
|
|
131
149
|
type FormValidationError = {
|
|
132
150
|
key: string;
|
|
133
|
-
value:
|
|
151
|
+
value: FormValue;
|
|
134
152
|
};
|
|
135
153
|
type FormValidationErrors = FormValidationError[];
|
|
136
154
|
type FormState<T> = {
|
|
@@ -143,7 +161,7 @@ type IFormBuilderControlSchema = {
|
|
|
143
161
|
schema: ControlType;
|
|
144
162
|
name?: string;
|
|
145
163
|
label?: string;
|
|
146
|
-
value?:
|
|
164
|
+
value?: FormValue;
|
|
147
165
|
placeholder?: string;
|
|
148
166
|
required?: FormActivator;
|
|
149
167
|
hidden?: FormActivator;
|
|
@@ -164,15 +182,12 @@ type IFormBuilderGroupValues = {
|
|
|
164
182
|
[key: string]: FormGroup | FormArray | FormControl;
|
|
165
183
|
};
|
|
166
184
|
type IFormBuilderSchema = IFormBuilderGroupSchema | IFormBuilderArraySchema;
|
|
167
|
-
type StateValue = StateValue[] | {
|
|
168
|
-
[key: string]: StateValue;
|
|
169
|
-
} | number | string | boolean | null | undefined;
|
|
170
185
|
|
|
171
186
|
declare class FormAbstract extends EventEmitter {
|
|
172
187
|
errors_: ValidationError;
|
|
173
|
-
value_:
|
|
188
|
+
value_: FormValue;
|
|
174
189
|
validators_: FormValidator[];
|
|
175
|
-
state_:
|
|
190
|
+
state_: FormFlags;
|
|
176
191
|
name?: string | number;
|
|
177
192
|
parent?: FormCollection;
|
|
178
193
|
schema: ControlType;
|
|
@@ -182,10 +197,10 @@ declare class FormAbstract extends EventEmitter {
|
|
|
182
197
|
};
|
|
183
198
|
protected initialOptions_?: FormOptions;
|
|
184
199
|
private markAsDirty_;
|
|
185
|
-
constructor(value:
|
|
200
|
+
constructor(value: FormValue, validators?: (FormValidator | FormValidator[]));
|
|
186
201
|
protected setInitialOptions(options?: FormOptions): void;
|
|
187
202
|
protected checkAsyncState_(root?: FormCollection): Promise<boolean>;
|
|
188
|
-
protected checkAsyncPropState_(key:
|
|
203
|
+
protected checkAsyncPropState_(key: keyof FormFlags, option?: FormActivator, root?: FormCollection): Promise<boolean>;
|
|
189
204
|
protected revalidate_(): Promise<void>;
|
|
190
205
|
protected validate_(root?: FormCollection): Promise<void>;
|
|
191
206
|
validateAndChange_(root?: FormCollection): Promise<void>;
|
|
@@ -193,7 +208,7 @@ declare class FormAbstract extends EventEmitter {
|
|
|
193
208
|
protected change_(propagate?: boolean): void;
|
|
194
209
|
protected updateState_(): void;
|
|
195
210
|
reset(): void;
|
|
196
|
-
patch(value:
|
|
211
|
+
patch(value: FormValue): void;
|
|
197
212
|
addValidators(...validators: FormValidator[]): void;
|
|
198
213
|
replaceValidators(...validators: FormValidator[]): void;
|
|
199
214
|
clearValidators(): void;
|
|
@@ -207,34 +222,33 @@ declare class FormAbstract extends EventEmitter {
|
|
|
207
222
|
set placeholder(placeholder: string);
|
|
208
223
|
get validators(): FormValidator[];
|
|
209
224
|
set validators(validators: FormValidator[]);
|
|
210
|
-
get state():
|
|
225
|
+
get state(): FormFlags;
|
|
211
226
|
get errors(): ValidationError;
|
|
212
|
-
get invalid():
|
|
213
|
-
get disabled():
|
|
214
|
-
set disabled(disabled:
|
|
215
|
-
get hidden():
|
|
216
|
-
set hidden(hidden:
|
|
217
|
-
get readonly():
|
|
218
|
-
set readonly(readonly:
|
|
219
|
-
get dirty():
|
|
220
|
-
set dirty(dirty:
|
|
221
|
-
get touched():
|
|
222
|
-
set touched(touched:
|
|
223
|
-
get submitted():
|
|
224
|
-
set submitted(submitted:
|
|
225
|
-
get valid():
|
|
226
|
-
get enabled():
|
|
227
|
-
get visible():
|
|
228
|
-
get writeable():
|
|
229
|
-
get pristine():
|
|
230
|
-
get untouched():
|
|
231
|
-
get unsubmitted():
|
|
227
|
+
get invalid(): boolean;
|
|
228
|
+
get disabled(): boolean;
|
|
229
|
+
set disabled(disabled: boolean);
|
|
230
|
+
get hidden(): boolean;
|
|
231
|
+
set hidden(hidden: boolean);
|
|
232
|
+
get readonly(): boolean;
|
|
233
|
+
set readonly(readonly: boolean);
|
|
234
|
+
get dirty(): boolean;
|
|
235
|
+
set dirty(dirty: boolean);
|
|
236
|
+
get touched(): boolean;
|
|
237
|
+
set touched(touched: boolean);
|
|
238
|
+
get submitted(): boolean;
|
|
239
|
+
set submitted(submitted: boolean);
|
|
240
|
+
get valid(): boolean;
|
|
241
|
+
get enabled(): boolean;
|
|
242
|
+
get visible(): boolean;
|
|
243
|
+
get writeable(): boolean;
|
|
244
|
+
get pristine(): boolean;
|
|
245
|
+
get untouched(): boolean;
|
|
246
|
+
get unsubmitted(): boolean;
|
|
232
247
|
get value(): any;
|
|
233
248
|
set value(value: any);
|
|
234
249
|
}
|
|
235
250
|
|
|
236
|
-
declare function validValue(value:
|
|
237
|
-
declare function isThenable(result: any): any;
|
|
251
|
+
declare function validValue(value: FormValue): any;
|
|
238
252
|
declare function mapErrors_(errors: FormErrors): FormValidationError[];
|
|
239
253
|
declare function valueToString(value: IOption | IOption[] | IEquatable | IEquatable[] | null): string | string[] | undefined;
|
|
240
254
|
declare function stringToValue(value: string | string[] | undefined, options?: IOption[], optionsExtra?: {
|
|
@@ -249,7 +263,7 @@ declare function EmailValidator(): FormValidator;
|
|
|
249
263
|
/**
|
|
250
264
|
* an equality match validation on another field
|
|
251
265
|
*/
|
|
252
|
-
declare function MatchValidator(getOtherValue: (value:
|
|
266
|
+
declare function MatchValidator(getOtherValue: (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormAbstract) => any): FormValidator;
|
|
253
267
|
|
|
254
268
|
/**
|
|
255
269
|
* a max string length validator
|
|
@@ -284,7 +298,7 @@ declare function PatternValidator(pattern: string | RegExp): FormValidator;
|
|
|
284
298
|
/**
|
|
285
299
|
* a required dependant on another field
|
|
286
300
|
*/
|
|
287
|
-
declare function RequiredIfValidator(condition: (value:
|
|
301
|
+
declare function RequiredIfValidator(condition: (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormAbstract) => boolean): FormValidator;
|
|
288
302
|
|
|
289
303
|
/**
|
|
290
304
|
* a required and true validator
|
|
@@ -302,4 +316,4 @@ declare function useForm<T, U extends (FormGroup | FormArray)>(factory: () => U,
|
|
|
302
316
|
|
|
303
317
|
declare function useFormBuilder<T, U extends (FormGroup | FormArray)>(schema: IFormBuilderSchema, deps?: DependencyList): [FormState<T>, (value: Partial<T>) => void, () => void, () => void, U];
|
|
304
318
|
|
|
305
|
-
export { ControlType, EmailValidator, FormAbstract, FormAbstractCollection, FormActivator, FormArray, FormAsyncValidator, FormCollection, FormControl, FormControls, FormErrors, FormFlags, FormGroup, FormOptions, FormState, FormValidationError, FormValidationErrors, FormValidator, IControlParam, IFormBuilderArraySchema, IFormBuilderControlSchema, IFormBuilderGroupSchema, IFormBuilderGroupValues, IFormBuilderSchema, IFormOption, MatchValidator, MaxLengthValidator, MaxValidator, MinLengthValidator, MinValidator, NullValidator, PatternValidator, RequiredIfValidator, RequiredTrueValidator, RequiredValidator,
|
|
319
|
+
export { ControlType, EmailValidator, FormAbstract, FormAbstractCollection, FormActivator, FormArray, FormAsyncValidator, FormCollection, FormControl, FormControls, FormErrors, FormFlags, FormGroup, FormOptions, FormState, FormValidationError, FormValidationErrors, FormValidator, FormValue, FormValueArray, FormValueGroup, IControlParam, IFormBuilderArraySchema, IFormBuilderControlSchema, IFormBuilderGroupSchema, IFormBuilderGroupValues, IFormBuilderSchema, IFormOption, MatchValidator, MaxLengthValidator, MaxValidator, MinLengthValidator, MinValidator, NullValidator, PatternValidator, RequiredIfValidator, RequiredTrueValidator, RequiredValidator, ValidationError, formArray, formControl, formGroup, mapErrors_, stringToValue, useControl, useForm, useFormBuilder, validValue, valueToString };
|
package/dist/index.js
CHANGED
|
@@ -73,7 +73,6 @@ __export(src_exports, {
|
|
|
73
73
|
formArray: () => formArray,
|
|
74
74
|
formControl: () => formControl,
|
|
75
75
|
formGroup: () => formGroup,
|
|
76
|
-
isThenable: () => isThenable,
|
|
77
76
|
mapErrors_: () => mapErrors_,
|
|
78
77
|
stringToValue: () => stringToValue,
|
|
79
78
|
useControl: () => useControl,
|
|
@@ -84,6 +83,9 @@ __export(src_exports, {
|
|
|
84
83
|
});
|
|
85
84
|
module.exports = __toCommonJS(src_exports);
|
|
86
85
|
|
|
86
|
+
// src/forms/form-abstract.ts
|
|
87
|
+
var import_bom_core = require("@websolutespa/bom-core");
|
|
88
|
+
|
|
87
89
|
// src/forms/event-emitter.ts
|
|
88
90
|
var EventEmitter = class {
|
|
89
91
|
constructor() {
|
|
@@ -123,9 +125,6 @@ var EventEmitter = class {
|
|
|
123
125
|
function validValue(value) {
|
|
124
126
|
return value !== void 0 && value !== "" ? value : null;
|
|
125
127
|
}
|
|
126
|
-
function isThenable(result) {
|
|
127
|
-
return result && typeof result.then === "function";
|
|
128
|
-
}
|
|
129
128
|
function mapErrors_(errors) {
|
|
130
129
|
return Object.keys(errors).map((key) => ({ key, value: errors[key] }));
|
|
131
130
|
}
|
|
@@ -233,7 +232,7 @@ var FormAbstract = class extends EventEmitter {
|
|
|
233
232
|
let dirty = false;
|
|
234
233
|
if (typeof option === "function") {
|
|
235
234
|
let result = option(this.value_, root == null ? void 0 : root.value, this, root);
|
|
236
|
-
result =
|
|
235
|
+
result = (0, import_bom_core.isPromise)(result) ? yield result : result;
|
|
237
236
|
if (this.state_[key] !== result) {
|
|
238
237
|
this.state_[key] = result;
|
|
239
238
|
dirty = true;
|
|
@@ -259,7 +258,7 @@ var FormAbstract = class extends EventEmitter {
|
|
|
259
258
|
} else {
|
|
260
259
|
const validations = this.validators_.map((x) => x(this.value_, root == null ? void 0 : root.value, this, root)).filter((x) => x);
|
|
261
260
|
const { results, promises } = validations.reduce((p, c) => {
|
|
262
|
-
|
|
261
|
+
(0, import_bom_core.isPromise)(c) ? p.promises.push(c) : p.results.push(c);
|
|
263
262
|
return p;
|
|
264
263
|
}, { results: [], promises: [] });
|
|
265
264
|
promises.forEach((x) => x.then((result) => {
|
|
@@ -522,6 +521,9 @@ var FormAbstract = class extends EventEmitter {
|
|
|
522
521
|
*/
|
|
523
522
|
};
|
|
524
523
|
|
|
524
|
+
// src/forms/form-abstract-collection.ts
|
|
525
|
+
var import_bom_core2 = require("@websolutespa/bom-core");
|
|
526
|
+
|
|
525
527
|
// src/forms/form-control.ts
|
|
526
528
|
var FormControl = class extends FormAbstract {
|
|
527
529
|
constructor(value = null, validators, initialOptions) {
|
|
@@ -593,7 +595,7 @@ var FormAbstractCollection = class extends FormAbstract {
|
|
|
593
595
|
let dirty = false;
|
|
594
596
|
if (typeof option === "function") {
|
|
595
597
|
let result = option(this.value_, root == null ? void 0 : root.value, this, root);
|
|
596
|
-
result =
|
|
598
|
+
result = (0, import_bom_core2.isPromise)(result) ? yield result : result;
|
|
597
599
|
this.forEach_((control) => {
|
|
598
600
|
if (control.state_[key] !== result) {
|
|
599
601
|
control.state_[key] = result;
|
|
@@ -859,10 +861,11 @@ function formGroup(controls = {}, validators) {
|
|
|
859
861
|
function EmailValidator() {
|
|
860
862
|
const regex = /^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[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])?)*$/;
|
|
861
863
|
return function(value) {
|
|
862
|
-
if (
|
|
864
|
+
if (typeof value === "string") {
|
|
865
|
+
return regex.test(value) ? null : { email: true };
|
|
866
|
+
} else {
|
|
863
867
|
return null;
|
|
864
868
|
}
|
|
865
|
-
return regex.test(value) ? null : { email: true };
|
|
866
869
|
};
|
|
867
870
|
}
|
|
868
871
|
|
|
@@ -878,21 +881,25 @@ function MatchValidator(getOtherValue) {
|
|
|
878
881
|
// src/forms/validators/max-length.validator.ts
|
|
879
882
|
function MaxLengthValidator(maxlength) {
|
|
880
883
|
return function(value) {
|
|
881
|
-
if (
|
|
884
|
+
if (maxlength == null) {
|
|
885
|
+
return null;
|
|
886
|
+
}
|
|
887
|
+
if (typeof value === "string") {
|
|
888
|
+
const length = value ? value.length : 0;
|
|
889
|
+
return length > maxlength ? { minlength: { requiredLength: maxlength, actualLength: length } } : null;
|
|
890
|
+
} else {
|
|
882
891
|
return null;
|
|
883
892
|
}
|
|
884
|
-
const length = value ? value.length : 0;
|
|
885
|
-
return length > maxlength ? { minlength: { requiredLength: maxlength, actualLength: length } } : null;
|
|
886
893
|
};
|
|
887
894
|
}
|
|
888
895
|
|
|
889
896
|
// src/forms/validators/max.validator.ts
|
|
890
897
|
function MaxValidator(max) {
|
|
891
898
|
return function(value) {
|
|
899
|
+
value = typeof value === "string" ? parseFloat(value) : typeof value === "number" ? value : null;
|
|
892
900
|
if (value == null || max == null) {
|
|
893
901
|
return null;
|
|
894
902
|
}
|
|
895
|
-
value = parseFloat(value);
|
|
896
903
|
return !isNaN(value) && value > max ? { max: { max, actual: value } } : null;
|
|
897
904
|
};
|
|
898
905
|
}
|
|
@@ -900,21 +907,25 @@ function MaxValidator(max) {
|
|
|
900
907
|
// src/forms/validators/min-length.validator.ts
|
|
901
908
|
function MinLengthValidator(minlength) {
|
|
902
909
|
return function(value) {
|
|
903
|
-
if (
|
|
910
|
+
if (minlength == null) {
|
|
911
|
+
return null;
|
|
912
|
+
}
|
|
913
|
+
if (typeof value === "string") {
|
|
914
|
+
const length = value ? value.length : 0;
|
|
915
|
+
return length < minlength ? { minlength: { requiredLength: minlength, actualLength: length } } : null;
|
|
916
|
+
} else {
|
|
904
917
|
return null;
|
|
905
918
|
}
|
|
906
|
-
const length = value ? value.length : 0;
|
|
907
|
-
return length < minlength ? { minlength: { requiredLength: minlength, actualLength: length } } : null;
|
|
908
919
|
};
|
|
909
920
|
}
|
|
910
921
|
|
|
911
922
|
// src/forms/validators/min.validator.ts
|
|
912
923
|
function MinValidator(min) {
|
|
913
924
|
return function(value) {
|
|
925
|
+
value = typeof value === "string" ? parseFloat(value) : typeof value === "number" ? value : null;
|
|
914
926
|
if (value == null || min == null) {
|
|
915
927
|
return null;
|
|
916
928
|
}
|
|
917
|
-
value = parseFloat(value);
|
|
918
929
|
return !isNaN(value) && value < min ? { min: { min, actual: value } } : null;
|
|
919
930
|
};
|
|
920
931
|
}
|
|
@@ -929,11 +940,15 @@ function NullValidator() {
|
|
|
929
940
|
// src/forms/validators/pattern.validator.ts
|
|
930
941
|
function PatternValidator(pattern) {
|
|
931
942
|
return function(value) {
|
|
932
|
-
if (
|
|
943
|
+
if (pattern == null) {
|
|
944
|
+
return null;
|
|
945
|
+
}
|
|
946
|
+
if (typeof value === "string") {
|
|
947
|
+
const regex = patternToRegEx(pattern);
|
|
948
|
+
return regex.test(value) ? null : { pattern: { requiredPattern: regex.toString(), actualValue: value } };
|
|
949
|
+
} else {
|
|
933
950
|
return null;
|
|
934
951
|
}
|
|
935
|
-
const regex = patternToRegEx(pattern);
|
|
936
|
-
return regex.test(value) ? null : { pattern: { requiredPattern: regex.toString(), actualValue: value } };
|
|
937
952
|
};
|
|
938
953
|
}
|
|
939
954
|
function patternToRegEx(pattern) {
|
|
@@ -949,10 +964,16 @@ function patternToRegEx(pattern) {
|
|
|
949
964
|
}
|
|
950
965
|
|
|
951
966
|
// src/forms/validators/required-if.validator.ts
|
|
967
|
+
var import_bom_core3 = require("@websolutespa/bom-core");
|
|
952
968
|
function RequiredIfValidator(condition) {
|
|
953
969
|
return function(value, rootValue, control, root) {
|
|
970
|
+
console.log("RequiredIfValidator", value, Boolean(condition(value, rootValue, control, root)));
|
|
954
971
|
if (Boolean(condition(value, rootValue, control, root)) === true) {
|
|
955
|
-
|
|
972
|
+
if ((0, import_bom_core3.isArray)(value) || typeof value === "string") {
|
|
973
|
+
return value.length === 0 ? { required: true } : null;
|
|
974
|
+
} else {
|
|
975
|
+
return value == null ? { required: true } : null;
|
|
976
|
+
}
|
|
956
977
|
} else {
|
|
957
978
|
return null;
|
|
958
979
|
}
|
|
@@ -967,9 +988,14 @@ function RequiredTrueValidator() {
|
|
|
967
988
|
}
|
|
968
989
|
|
|
969
990
|
// src/forms/validators/required.validator.ts
|
|
991
|
+
var import_bom_core4 = require("@websolutespa/bom-core");
|
|
970
992
|
function RequiredValidator() {
|
|
971
993
|
return function(value) {
|
|
972
|
-
|
|
994
|
+
if ((0, import_bom_core4.isArray)(value) || typeof value === "string") {
|
|
995
|
+
return value.length === 0 ? { required: true } : null;
|
|
996
|
+
} else {
|
|
997
|
+
return value == null ? { required: true } : null;
|
|
998
|
+
}
|
|
973
999
|
};
|
|
974
1000
|
}
|
|
975
1001
|
|
|
@@ -1053,7 +1079,7 @@ function useFormBuilder(schema, deps = []) {
|
|
|
1053
1079
|
setState(newState);
|
|
1054
1080
|
};
|
|
1055
1081
|
collection.on("change", onChange);
|
|
1056
|
-
collection.
|
|
1082
|
+
collection.revalidate_();
|
|
1057
1083
|
return () => collection.off("change", onChange);
|
|
1058
1084
|
}, deps);
|
|
1059
1085
|
return [state, setValue, setTouched, reset, collection];
|
|
@@ -1105,7 +1131,6 @@ function mapSchema_(schema) {
|
|
|
1105
1131
|
formArray,
|
|
1106
1132
|
formControl,
|
|
1107
1133
|
formGroup,
|
|
1108
|
-
isThenable,
|
|
1109
1134
|
mapErrors_,
|
|
1110
1135
|
stringToValue,
|
|
1111
1136
|
useControl,
|
package/dist/index.mjs
CHANGED
|
@@ -35,6 +35,9 @@ var __async = (__this, __arguments, generator) => {
|
|
|
35
35
|
});
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
+
// src/forms/form-abstract.ts
|
|
39
|
+
import { isPromise } from "@websolutespa/bom-core";
|
|
40
|
+
|
|
38
41
|
// src/forms/event-emitter.ts
|
|
39
42
|
var EventEmitter = class {
|
|
40
43
|
constructor() {
|
|
@@ -74,9 +77,6 @@ var EventEmitter = class {
|
|
|
74
77
|
function validValue(value) {
|
|
75
78
|
return value !== void 0 && value !== "" ? value : null;
|
|
76
79
|
}
|
|
77
|
-
function isThenable(result) {
|
|
78
|
-
return result && typeof result.then === "function";
|
|
79
|
-
}
|
|
80
80
|
function mapErrors_(errors) {
|
|
81
81
|
return Object.keys(errors).map((key) => ({ key, value: errors[key] }));
|
|
82
82
|
}
|
|
@@ -184,7 +184,7 @@ var FormAbstract = class extends EventEmitter {
|
|
|
184
184
|
let dirty = false;
|
|
185
185
|
if (typeof option === "function") {
|
|
186
186
|
let result = option(this.value_, root == null ? void 0 : root.value, this, root);
|
|
187
|
-
result =
|
|
187
|
+
result = isPromise(result) ? yield result : result;
|
|
188
188
|
if (this.state_[key] !== result) {
|
|
189
189
|
this.state_[key] = result;
|
|
190
190
|
dirty = true;
|
|
@@ -210,7 +210,7 @@ var FormAbstract = class extends EventEmitter {
|
|
|
210
210
|
} else {
|
|
211
211
|
const validations = this.validators_.map((x) => x(this.value_, root == null ? void 0 : root.value, this, root)).filter((x) => x);
|
|
212
212
|
const { results, promises } = validations.reduce((p, c) => {
|
|
213
|
-
|
|
213
|
+
isPromise(c) ? p.promises.push(c) : p.results.push(c);
|
|
214
214
|
return p;
|
|
215
215
|
}, { results: [], promises: [] });
|
|
216
216
|
promises.forEach((x) => x.then((result) => {
|
|
@@ -473,6 +473,9 @@ var FormAbstract = class extends EventEmitter {
|
|
|
473
473
|
*/
|
|
474
474
|
};
|
|
475
475
|
|
|
476
|
+
// src/forms/form-abstract-collection.ts
|
|
477
|
+
import { isPromise as isPromise2 } from "@websolutespa/bom-core";
|
|
478
|
+
|
|
476
479
|
// src/forms/form-control.ts
|
|
477
480
|
var FormControl = class extends FormAbstract {
|
|
478
481
|
constructor(value = null, validators, initialOptions) {
|
|
@@ -544,7 +547,7 @@ var FormAbstractCollection = class extends FormAbstract {
|
|
|
544
547
|
let dirty = false;
|
|
545
548
|
if (typeof option === "function") {
|
|
546
549
|
let result = option(this.value_, root == null ? void 0 : root.value, this, root);
|
|
547
|
-
result =
|
|
550
|
+
result = isPromise2(result) ? yield result : result;
|
|
548
551
|
this.forEach_((control) => {
|
|
549
552
|
if (control.state_[key] !== result) {
|
|
550
553
|
control.state_[key] = result;
|
|
@@ -810,10 +813,11 @@ function formGroup(controls = {}, validators) {
|
|
|
810
813
|
function EmailValidator() {
|
|
811
814
|
const regex = /^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[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])?)*$/;
|
|
812
815
|
return function(value) {
|
|
813
|
-
if (
|
|
816
|
+
if (typeof value === "string") {
|
|
817
|
+
return regex.test(value) ? null : { email: true };
|
|
818
|
+
} else {
|
|
814
819
|
return null;
|
|
815
820
|
}
|
|
816
|
-
return regex.test(value) ? null : { email: true };
|
|
817
821
|
};
|
|
818
822
|
}
|
|
819
823
|
|
|
@@ -829,21 +833,25 @@ function MatchValidator(getOtherValue) {
|
|
|
829
833
|
// src/forms/validators/max-length.validator.ts
|
|
830
834
|
function MaxLengthValidator(maxlength) {
|
|
831
835
|
return function(value) {
|
|
832
|
-
if (
|
|
836
|
+
if (maxlength == null) {
|
|
837
|
+
return null;
|
|
838
|
+
}
|
|
839
|
+
if (typeof value === "string") {
|
|
840
|
+
const length = value ? value.length : 0;
|
|
841
|
+
return length > maxlength ? { minlength: { requiredLength: maxlength, actualLength: length } } : null;
|
|
842
|
+
} else {
|
|
833
843
|
return null;
|
|
834
844
|
}
|
|
835
|
-
const length = value ? value.length : 0;
|
|
836
|
-
return length > maxlength ? { minlength: { requiredLength: maxlength, actualLength: length } } : null;
|
|
837
845
|
};
|
|
838
846
|
}
|
|
839
847
|
|
|
840
848
|
// src/forms/validators/max.validator.ts
|
|
841
849
|
function MaxValidator(max) {
|
|
842
850
|
return function(value) {
|
|
851
|
+
value = typeof value === "string" ? parseFloat(value) : typeof value === "number" ? value : null;
|
|
843
852
|
if (value == null || max == null) {
|
|
844
853
|
return null;
|
|
845
854
|
}
|
|
846
|
-
value = parseFloat(value);
|
|
847
855
|
return !isNaN(value) && value > max ? { max: { max, actual: value } } : null;
|
|
848
856
|
};
|
|
849
857
|
}
|
|
@@ -851,21 +859,25 @@ function MaxValidator(max) {
|
|
|
851
859
|
// src/forms/validators/min-length.validator.ts
|
|
852
860
|
function MinLengthValidator(minlength) {
|
|
853
861
|
return function(value) {
|
|
854
|
-
if (
|
|
862
|
+
if (minlength == null) {
|
|
863
|
+
return null;
|
|
864
|
+
}
|
|
865
|
+
if (typeof value === "string") {
|
|
866
|
+
const length = value ? value.length : 0;
|
|
867
|
+
return length < minlength ? { minlength: { requiredLength: minlength, actualLength: length } } : null;
|
|
868
|
+
} else {
|
|
855
869
|
return null;
|
|
856
870
|
}
|
|
857
|
-
const length = value ? value.length : 0;
|
|
858
|
-
return length < minlength ? { minlength: { requiredLength: minlength, actualLength: length } } : null;
|
|
859
871
|
};
|
|
860
872
|
}
|
|
861
873
|
|
|
862
874
|
// src/forms/validators/min.validator.ts
|
|
863
875
|
function MinValidator(min) {
|
|
864
876
|
return function(value) {
|
|
877
|
+
value = typeof value === "string" ? parseFloat(value) : typeof value === "number" ? value : null;
|
|
865
878
|
if (value == null || min == null) {
|
|
866
879
|
return null;
|
|
867
880
|
}
|
|
868
|
-
value = parseFloat(value);
|
|
869
881
|
return !isNaN(value) && value < min ? { min: { min, actual: value } } : null;
|
|
870
882
|
};
|
|
871
883
|
}
|
|
@@ -880,11 +892,15 @@ function NullValidator() {
|
|
|
880
892
|
// src/forms/validators/pattern.validator.ts
|
|
881
893
|
function PatternValidator(pattern) {
|
|
882
894
|
return function(value) {
|
|
883
|
-
if (
|
|
895
|
+
if (pattern == null) {
|
|
896
|
+
return null;
|
|
897
|
+
}
|
|
898
|
+
if (typeof value === "string") {
|
|
899
|
+
const regex = patternToRegEx(pattern);
|
|
900
|
+
return regex.test(value) ? null : { pattern: { requiredPattern: regex.toString(), actualValue: value } };
|
|
901
|
+
} else {
|
|
884
902
|
return null;
|
|
885
903
|
}
|
|
886
|
-
const regex = patternToRegEx(pattern);
|
|
887
|
-
return regex.test(value) ? null : { pattern: { requiredPattern: regex.toString(), actualValue: value } };
|
|
888
904
|
};
|
|
889
905
|
}
|
|
890
906
|
function patternToRegEx(pattern) {
|
|
@@ -900,10 +916,16 @@ function patternToRegEx(pattern) {
|
|
|
900
916
|
}
|
|
901
917
|
|
|
902
918
|
// src/forms/validators/required-if.validator.ts
|
|
919
|
+
import { isArray } from "@websolutespa/bom-core";
|
|
903
920
|
function RequiredIfValidator(condition) {
|
|
904
921
|
return function(value, rootValue, control, root) {
|
|
922
|
+
console.log("RequiredIfValidator", value, Boolean(condition(value, rootValue, control, root)));
|
|
905
923
|
if (Boolean(condition(value, rootValue, control, root)) === true) {
|
|
906
|
-
|
|
924
|
+
if (isArray(value) || typeof value === "string") {
|
|
925
|
+
return value.length === 0 ? { required: true } : null;
|
|
926
|
+
} else {
|
|
927
|
+
return value == null ? { required: true } : null;
|
|
928
|
+
}
|
|
907
929
|
} else {
|
|
908
930
|
return null;
|
|
909
931
|
}
|
|
@@ -918,9 +940,14 @@ function RequiredTrueValidator() {
|
|
|
918
940
|
}
|
|
919
941
|
|
|
920
942
|
// src/forms/validators/required.validator.ts
|
|
943
|
+
import { isArray as isArray2 } from "@websolutespa/bom-core";
|
|
921
944
|
function RequiredValidator() {
|
|
922
945
|
return function(value) {
|
|
923
|
-
|
|
946
|
+
if (isArray2(value) || typeof value === "string") {
|
|
947
|
+
return value.length === 0 ? { required: true } : null;
|
|
948
|
+
} else {
|
|
949
|
+
return value == null ? { required: true } : null;
|
|
950
|
+
}
|
|
924
951
|
};
|
|
925
952
|
}
|
|
926
953
|
|
|
@@ -1004,7 +1031,7 @@ function useFormBuilder(schema, deps = []) {
|
|
|
1004
1031
|
setState(newState);
|
|
1005
1032
|
};
|
|
1006
1033
|
collection.on("change", onChange);
|
|
1007
|
-
collection.
|
|
1034
|
+
collection.revalidate_();
|
|
1008
1035
|
return () => collection.off("change", onChange);
|
|
1009
1036
|
}, deps);
|
|
1010
1037
|
return [state, setValue, setTouched, reset, collection];
|
|
@@ -1055,7 +1082,6 @@ export {
|
|
|
1055
1082
|
formArray,
|
|
1056
1083
|
formControl,
|
|
1057
1084
|
formGroup,
|
|
1058
|
-
isThenable,
|
|
1059
1085
|
mapErrors_,
|
|
1060
1086
|
stringToValue,
|
|
1061
1087
|
useControl,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@websolutespa/bom-mixer-forms",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "Mixer Forms module of the BOM Repository",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bom",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@websolutespa/bom-cli": "*",
|
|
35
35
|
"@websolutespa/test": "*",
|
|
36
36
|
"@websolutespa/tsconfig": "*",
|
|
37
|
-
"eslint": "^
|
|
37
|
+
"eslint": "^8.56.0",
|
|
38
38
|
"eslint-config-websolute": "*",
|
|
39
39
|
"raw-loader": "^4.0.2",
|
|
40
40
|
"ts-node": "^10.9.2",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { isPromise } from '@websolutespa/bom-core';
|
|
1
2
|
import { FormAbstract } from './form-abstract';
|
|
2
3
|
import { FormControl } from './form-control';
|
|
3
|
-
import { FormActivator, FormCollection, FormControls, FormOptions, FormValidator } from './types';
|
|
4
|
-
import { isThenable } from './utils';
|
|
4
|
+
import { FormActivator, FormCollection, FormControls, FormFlags, FormOptions, FormValidator, FormValue } from './types';
|
|
5
5
|
|
|
6
6
|
export class FormAbstractCollection<T extends FormControls> extends FormAbstract {
|
|
7
7
|
|
|
@@ -72,12 +72,12 @@ export class FormAbstractCollection<T extends FormControls> extends FormAbstract
|
|
|
72
72
|
this.updateState_();
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
protected async checkAsyncPropState_(key:
|
|
75
|
+
protected async checkAsyncPropState_(key: keyof FormFlags, option?: FormActivator, root?: FormCollection): Promise<boolean> {
|
|
76
76
|
let dirty = false;
|
|
77
77
|
if (typeof option === 'function') {
|
|
78
78
|
let result = option(this.value_, root?.value, this, root);
|
|
79
79
|
// console.log('checkAsyncPropState_', result);
|
|
80
|
-
result =
|
|
80
|
+
result = isPromise(result) ? await result : result;
|
|
81
81
|
this.forEach_((control: FormAbstract) => {
|
|
82
82
|
if (control.state_[key] !== result) {
|
|
83
83
|
control.state_[key] = result;
|
|
@@ -280,8 +280,8 @@ export class FormAbstractCollection<T extends FormControls> extends FormAbstract
|
|
|
280
280
|
});
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
-
get value(): { [key: string]:
|
|
284
|
-
return this.reduce_((result: { [key: string]:
|
|
283
|
+
get value(): { [key: string]: FormValue } {
|
|
284
|
+
return this.reduce_((result: { [key: string]: FormValue }, control: FormAbstract, key: string) => {
|
|
285
285
|
if (control.enabled) {
|
|
286
286
|
result[key] = control.value;
|
|
287
287
|
}
|
|
@@ -289,7 +289,7 @@ export class FormAbstractCollection<T extends FormControls> extends FormAbstract
|
|
|
289
289
|
}, {});
|
|
290
290
|
}
|
|
291
291
|
|
|
292
|
-
set value(value: { [key: string]:
|
|
292
|
+
set value(value: { [key: string]: FormValue }) {
|
|
293
293
|
this.forEach_((control: FormAbstract, key: string) => {
|
|
294
294
|
control.value = value[key];
|
|
295
295
|
});
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { IOption } from '@websolutespa/bom-core';
|
|
1
|
+
import { IOption, isPromise } from '@websolutespa/bom-core';
|
|
2
2
|
import { EventEmitter } from './event-emitter';
|
|
3
|
-
import { ControlType, FormActivator, FormCollection, FormOptions, FormValidator, ValidationError } from './types';
|
|
4
|
-
import {
|
|
3
|
+
import { ControlType, FormActivator, FormCollection, FormFlags, FormOptions, FormValidator, FormValue, ValidationError } from './types';
|
|
4
|
+
import { validValue } from './utils';
|
|
5
5
|
|
|
6
6
|
export class FormAbstract extends EventEmitter {
|
|
7
7
|
|
|
8
8
|
// callbacks_: Function[] = [];
|
|
9
9
|
errors_: ValidationError;
|
|
10
|
-
value_:
|
|
10
|
+
value_: FormValue;
|
|
11
11
|
validators_: FormValidator[];
|
|
12
|
-
state_:
|
|
12
|
+
state_: FormFlags;
|
|
13
13
|
name?: string | number;
|
|
14
14
|
parent?: FormCollection;
|
|
15
15
|
|
|
@@ -20,7 +20,7 @@ export class FormAbstract extends EventEmitter {
|
|
|
20
20
|
protected initialOptions_?: FormOptions;
|
|
21
21
|
private markAsDirty_: boolean = false;
|
|
22
22
|
|
|
23
|
-
constructor(value:
|
|
23
|
+
constructor(value: FormValue, validators?: (FormValidator | FormValidator[])) {
|
|
24
24
|
super();
|
|
25
25
|
this.errors_ = {};
|
|
26
26
|
this.value_ = validValue(value);
|
|
@@ -164,11 +164,11 @@ export class FormAbstract extends EventEmitter {
|
|
|
164
164
|
return dirty;
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
protected async checkAsyncPropState_(key:
|
|
167
|
+
protected async checkAsyncPropState_(key: keyof FormFlags, option?: FormActivator, root?: FormCollection): Promise<boolean> {
|
|
168
168
|
let dirty = false;
|
|
169
169
|
if (typeof option === 'function') {
|
|
170
170
|
let result = option(this.value_, root?.value, this, root);
|
|
171
|
-
result =
|
|
171
|
+
result = isPromise(result) ? await result : result;
|
|
172
172
|
if (this.state_[key] !== result) {
|
|
173
173
|
this.state_[key] = result;
|
|
174
174
|
dirty = true;
|
|
@@ -193,7 +193,7 @@ export class FormAbstract extends EventEmitter {
|
|
|
193
193
|
} else {
|
|
194
194
|
const validations = this.validators_.map((x) => x(this.value_, root?.value, this, root)).filter((x) => x);
|
|
195
195
|
const { results, promises } = validations.reduce((p: { results: (null | ValidationError)[], promises: Promise<null | ValidationError>[] }, c: (null | ValidationError) | Promise<null | ValidationError>) => {
|
|
196
|
-
|
|
196
|
+
isPromise(c) ? p.promises.push(c as Promise<null | ValidationError>) : p.results.push(c);
|
|
197
197
|
return p;
|
|
198
198
|
}, { results: [], promises: [] });
|
|
199
199
|
promises.forEach(x => x.then((result: null | ValidationError) => {
|
|
@@ -310,7 +310,7 @@ export class FormAbstract extends EventEmitter {
|
|
|
310
310
|
this.revalidate_();
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
-
patch(value:
|
|
313
|
+
patch(value: FormValue) {
|
|
314
314
|
this.value = value;
|
|
315
315
|
}
|
|
316
316
|
|
package/src/forms/form-array.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FormAbstract } from './form-abstract';
|
|
2
2
|
import { FormAbstractCollection } from './form-abstract-collection';
|
|
3
|
-
import { FormOptions, FormValidator } from './types';
|
|
3
|
+
import { FormOptions, FormValidator, FormValue } from './types';
|
|
4
4
|
|
|
5
5
|
export class FormArray extends FormAbstractCollection<FormAbstract[]> {
|
|
6
6
|
|
|
@@ -18,8 +18,8 @@ export class FormArray extends FormAbstractCollection<FormAbstract[]> {
|
|
|
18
18
|
return this.controls;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
get value():
|
|
22
|
-
return this.reduce_((result:
|
|
21
|
+
get value(): FormValue[] {
|
|
22
|
+
return this.reduce_((result: FormValue[], control: FormAbstract, key: number) => {
|
|
23
23
|
result[key] = control.value;
|
|
24
24
|
return result;
|
|
25
25
|
}, []); // init as array
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { FormAbstract } from './form-abstract';
|
|
2
|
-
import { FormOptions, FormValidator } from './types';
|
|
2
|
+
import { FormOptions, FormValidator, FormValue } from './types';
|
|
3
3
|
|
|
4
4
|
export class FormControl extends FormAbstract {
|
|
5
|
-
constructor(value:
|
|
5
|
+
constructor(value: FormValue = null, validators?: FormValidator | FormValidator[], initialOptions?: FormOptions) {
|
|
6
6
|
super(value, validators);
|
|
7
7
|
this.setInitialOptions(initialOptions);
|
|
8
8
|
// this.revalidate_();
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export function formControl(value:
|
|
12
|
+
export function formControl(value: FormValue = null, validators?: FormValidator | FormValidator[]) {
|
|
13
13
|
return new FormControl(value, validators);
|
|
14
14
|
}
|
package/src/forms/form-group.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FormAbstract } from './form-abstract';
|
|
2
2
|
import { FormAbstractCollection } from './form-abstract-collection';
|
|
3
|
-
import { FormOptions, FormValidator } from './types';
|
|
3
|
+
import { FormOptions, FormValidator, FormValue } from './types';
|
|
4
4
|
|
|
5
5
|
export class FormGroup extends FormAbstractCollection<{ [key: string]: FormAbstract }> {
|
|
6
6
|
constructor(controls: { [key: string]: FormAbstract | any } = {}, validators?: FormValidator | FormValidator[], initialOptions?: FormOptions) {
|
|
@@ -10,6 +10,6 @@ export class FormGroup extends FormAbstractCollection<{ [key: string]: FormAbstr
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export function formGroup(controls: { [key: string]: FormAbstract |
|
|
13
|
+
export function formGroup(controls: { [key: string]: FormAbstract | FormValue } = {}, validators?: FormValidator | FormValidator[]) {
|
|
14
14
|
return new FormGroup(controls, validators);
|
|
15
15
|
}
|
package/src/forms/types.ts
CHANGED
|
@@ -5,6 +5,12 @@ import { FormArray } from './form-array';
|
|
|
5
5
|
import { FormControl } from './form-control';
|
|
6
6
|
import { FormGroup } from './form-group';
|
|
7
7
|
|
|
8
|
+
export type FormValue = any; // string | number | boolean | null | Date | FormValueGroup | FormValueArray;
|
|
9
|
+
|
|
10
|
+
export type FormValueGroup = { [key: string]: FormValue };
|
|
11
|
+
|
|
12
|
+
export type FormValueArray = FormValue[];
|
|
13
|
+
|
|
8
14
|
export type IControlParam = { uid: number, control: FormControl };
|
|
9
15
|
|
|
10
16
|
export type IFormOption = { id: IEquatable, name: string };
|
|
@@ -13,7 +19,7 @@ export type FormOptions = {
|
|
|
13
19
|
schema?: ControlType;
|
|
14
20
|
name?: string,
|
|
15
21
|
label?: string,
|
|
16
|
-
value?:
|
|
22
|
+
value?: FormValue;
|
|
17
23
|
placeholder?: string,
|
|
18
24
|
required?: FormActivator,
|
|
19
25
|
hidden?: FormActivator,
|
|
@@ -27,15 +33,31 @@ export type ValidationError = {
|
|
|
27
33
|
[key: string]: any
|
|
28
34
|
};
|
|
29
35
|
|
|
30
|
-
export type FormControls = { [key: string]: FormAbstract } | FormAbstract[];
|
|
36
|
+
export type FormControls = { [key: string]: FormAbstract | FormValue } | FormAbstract[];
|
|
31
37
|
export type FormCollection = FormAbstractCollection<FormControls>;
|
|
32
|
-
export type FormActivator = boolean | ((value:
|
|
33
|
-
export type FormValidator = (value:
|
|
34
|
-
export type FormAsyncValidator = (value:
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
export type FormActivator = boolean | ((value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormCollection) => boolean | Promise<boolean>);
|
|
39
|
+
export type FormValidator = (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormCollection) => null | ValidationError;
|
|
40
|
+
export type FormAsyncValidator = (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormCollection) => Promise<null | ValidationError>;
|
|
41
|
+
export type FormFlags = {
|
|
42
|
+
invalid: boolean;
|
|
43
|
+
disabled: boolean;
|
|
44
|
+
hidden: boolean;
|
|
45
|
+
readonly: boolean;
|
|
46
|
+
dirty: boolean;
|
|
47
|
+
touched: boolean;
|
|
48
|
+
submitted: boolean;
|
|
49
|
+
// derived
|
|
50
|
+
valid: boolean;
|
|
51
|
+
enabled: boolean;
|
|
52
|
+
visible: boolean;
|
|
53
|
+
writeable: boolean;
|
|
54
|
+
pristine: boolean;
|
|
55
|
+
untouched: boolean;
|
|
56
|
+
unsubmitted: boolean;
|
|
57
|
+
};
|
|
58
|
+
// export type FormFlags = { [key: string]: boolean };
|
|
37
59
|
export type FormErrors = { [key: string]: any };
|
|
38
|
-
export type FormValidationError = { key: string, value:
|
|
60
|
+
export type FormValidationError = { key: string, value: FormValue };
|
|
39
61
|
export type FormValidationErrors = FormValidationError[];
|
|
40
62
|
|
|
41
63
|
export type FormState<T> = {
|
|
@@ -50,7 +72,7 @@ export type IFormBuilderControlSchema = {
|
|
|
50
72
|
schema: ControlType;
|
|
51
73
|
name?: string;
|
|
52
74
|
label?: string;
|
|
53
|
-
value?:
|
|
75
|
+
value?: FormValue;
|
|
54
76
|
placeholder?: string;
|
|
55
77
|
required?: FormActivator;
|
|
56
78
|
hidden?: FormActivator,
|
|
@@ -66,5 +88,3 @@ export type IFormBuilderGroupSchema = { [key: string]: IFormBuilderControlSchema
|
|
|
66
88
|
export type IFormBuilderArraySchema = IFormBuilderControlSchema[];
|
|
67
89
|
export type IFormBuilderGroupValues = { [key: string]: FormGroup | FormArray | FormControl };
|
|
68
90
|
export type IFormBuilderSchema = IFormBuilderGroupSchema | IFormBuilderArraySchema;
|
|
69
|
-
|
|
70
|
-
export type StateValue = StateValue[] | { [key: string]: StateValue } | number | string | boolean | null | undefined;
|
package/src/forms/utils.ts
CHANGED
|
@@ -1,35 +1,14 @@
|
|
|
1
1
|
import { IEquatable, IOption } from '@websolutespa/bom-core';
|
|
2
|
-
import { FormErrors, FormValidationError } from './types';
|
|
2
|
+
import { FormErrors, FormValidationError, FormValue } from './types';
|
|
3
3
|
|
|
4
|
-
export function validValue(value:
|
|
4
|
+
export function validValue(value: FormValue) {
|
|
5
5
|
return value !== undefined && value !== '' ? value : null;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
export function isThenable(result: any) {
|
|
9
|
-
return result && typeof result.then === 'function';
|
|
10
|
-
}
|
|
11
|
-
|
|
12
8
|
export function mapErrors_(errors: FormErrors): FormValidationError[] {
|
|
13
9
|
return Object.keys(errors).map(key => ({ key, value: errors[key] }));
|
|
14
10
|
}
|
|
15
11
|
|
|
16
|
-
/*
|
|
17
|
-
export function deepCopy<T>(source: T): T;
|
|
18
|
-
export function deepCopy(source: StateValue): StateValue {
|
|
19
|
-
if (Array.isArray(source)) {
|
|
20
|
-
return source.map(x => deepCopy(x));
|
|
21
|
-
} else if (source && typeof source === 'object') {
|
|
22
|
-
const copy: { [key: string]: any } = {};
|
|
23
|
-
Object.keys(source).forEach(key => {
|
|
24
|
-
copy[key] = deepCopy(source[key]);
|
|
25
|
-
});
|
|
26
|
-
return copy;
|
|
27
|
-
} else {
|
|
28
|
-
return source;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
12
|
export function valueToString(value: IOption | IOption[] | IEquatable | IEquatable[] | null): string | string[] | undefined {
|
|
34
13
|
function mapValue(value: IOption | IEquatable | null): string | undefined {
|
|
35
14
|
const stringValue = value != null ? (
|
|
@@ -6,9 +6,10 @@ import { FormValidator } from '../types';
|
|
|
6
6
|
export function EmailValidator(): FormValidator {
|
|
7
7
|
const regex = /^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[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])?)*$/;
|
|
8
8
|
return function (value) {
|
|
9
|
-
if (
|
|
9
|
+
if (typeof value === 'string') {
|
|
10
|
+
return regex.test(value) ? null : { email: true };
|
|
11
|
+
} else {
|
|
10
12
|
return null;
|
|
11
13
|
}
|
|
12
|
-
return regex.test(value) ? null : { email: true };
|
|
13
14
|
};
|
|
14
15
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { FormAbstract } from '../form-abstract';
|
|
2
|
-
import { FormValidator } from '../types';
|
|
2
|
+
import { FormValidator, FormValue } from '../types';
|
|
3
3
|
import { validValue } from '../utils';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* an equality match validation on another field
|
|
7
7
|
*/
|
|
8
|
-
export function MatchValidator(getOtherValue: (value:
|
|
8
|
+
export function MatchValidator(getOtherValue: (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormAbstract) => any): FormValidator {
|
|
9
9
|
return function (value, rootValue, control, root) {
|
|
10
10
|
let otherValue = getOtherValue(value, rootValue, control, root);
|
|
11
11
|
otherValue = validValue(otherValue);
|
|
@@ -5,10 +5,14 @@ import { FormValidator } from '../types';
|
|
|
5
5
|
*/
|
|
6
6
|
export function MaxLengthValidator(maxlength: number): FormValidator {
|
|
7
7
|
return function (value) {
|
|
8
|
-
if (
|
|
8
|
+
if (maxlength == null) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
if (typeof value === 'string') {
|
|
12
|
+
const length = value ? value.length : 0;
|
|
13
|
+
return length > maxlength ? { minlength: { requiredLength: maxlength, actualLength: length } } : null;
|
|
14
|
+
} else {
|
|
9
15
|
return null;
|
|
10
16
|
}
|
|
11
|
-
const length = value ? value.length : 0;
|
|
12
|
-
return length > maxlength ? { minlength: { requiredLength: maxlength, actualLength: length } } : null;
|
|
13
17
|
};
|
|
14
18
|
}
|
|
@@ -5,10 +5,10 @@ import { FormValidator } from '../types';
|
|
|
5
5
|
*/
|
|
6
6
|
export function MaxValidator(max: number): FormValidator {
|
|
7
7
|
return function (value) {
|
|
8
|
+
value = typeof value === 'string' ? parseFloat(value) : typeof value === 'number' ? value : null;
|
|
8
9
|
if (value == null || max == null) { // loose
|
|
9
10
|
return null;
|
|
10
11
|
}
|
|
11
|
-
value = parseFloat(value);
|
|
12
12
|
return !isNaN(value) && value > max ? { max: { max: max, actual: value } } : null;
|
|
13
13
|
};
|
|
14
14
|
}
|
|
@@ -5,10 +5,14 @@ import { FormValidator } from '../types';
|
|
|
5
5
|
*/
|
|
6
6
|
export function MinLengthValidator(minlength: number): FormValidator {
|
|
7
7
|
return function (value) {
|
|
8
|
-
if (
|
|
8
|
+
if (minlength == null) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
if (typeof value === 'string') {
|
|
12
|
+
const length = value ? value.length : 0;
|
|
13
|
+
return length < minlength ? { minlength: { requiredLength: minlength, actualLength: length } } : null;
|
|
14
|
+
} else {
|
|
9
15
|
return null;
|
|
10
16
|
}
|
|
11
|
-
const length = value ? value.length : 0;
|
|
12
|
-
return length < minlength ? { minlength: { requiredLength: minlength, actualLength: length } } : null;
|
|
13
17
|
};
|
|
14
18
|
}
|
|
@@ -5,10 +5,10 @@ import { FormValidator } from '../types';
|
|
|
5
5
|
*/
|
|
6
6
|
export function MinValidator(min: number): FormValidator {
|
|
7
7
|
return function (value) {
|
|
8
|
+
value = typeof value === 'string' ? parseFloat(value) : typeof value === 'number' ? value : null;
|
|
8
9
|
if (value == null || min == null) { // loose
|
|
9
10
|
return null;
|
|
10
11
|
}
|
|
11
|
-
value = parseFloat(value);
|
|
12
12
|
return !isNaN(value) && value < min ? { min: { min: min, actual: value } } : null;
|
|
13
13
|
};
|
|
14
14
|
}
|
|
@@ -5,11 +5,15 @@ import { FormValidator } from '../types';
|
|
|
5
5
|
*/
|
|
6
6
|
export function PatternValidator(pattern: string | RegExp): FormValidator {
|
|
7
7
|
return function (value) {
|
|
8
|
-
if (
|
|
8
|
+
if (pattern == null) { // loose
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
if (typeof value === 'string') {
|
|
12
|
+
const regex = patternToRegEx(pattern);
|
|
13
|
+
return regex.test(value) ? null : { pattern: { requiredPattern: regex.toString(), actualValue: value } };
|
|
14
|
+
} else {
|
|
9
15
|
return null;
|
|
10
16
|
}
|
|
11
|
-
const regex = patternToRegEx(pattern);
|
|
12
|
-
return regex.test(value) ? null : { pattern: { requiredPattern: regex.toString(), actualValue: value } };
|
|
13
17
|
};
|
|
14
18
|
}
|
|
15
19
|
|
|
@@ -1,14 +1,19 @@
|
|
|
1
|
+
import { isArray } from '@websolutespa/bom-core';
|
|
1
2
|
import { FormAbstract } from '../form-abstract';
|
|
2
|
-
import { FormValidator } from '../types';
|
|
3
|
+
import { FormValidator, FormValue } from '../types';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* a required dependant on another field
|
|
6
7
|
*/
|
|
7
|
-
export function RequiredIfValidator(condition: (value:
|
|
8
|
+
export function RequiredIfValidator(condition: (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormAbstract) => boolean): FormValidator {
|
|
8
9
|
return function (value, rootValue, control, root) {
|
|
9
|
-
|
|
10
|
+
console.log('RequiredIfValidator', value, Boolean(condition(value, rootValue, control, root)));
|
|
10
11
|
if (Boolean(condition(value, rootValue, control, root)) === true) {
|
|
11
|
-
|
|
12
|
+
if (isArray(value) || typeof value === 'string') {
|
|
13
|
+
return (value.length === 0) ? { required: true } : null;
|
|
14
|
+
} else {
|
|
15
|
+
return value == null ? { required: true } : null;
|
|
16
|
+
}
|
|
12
17
|
} else {
|
|
13
18
|
return null;
|
|
14
19
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isArray } from '@websolutespa/bom-core';
|
|
1
2
|
import { FormValidator } from '../types';
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -6,7 +7,11 @@ import { FormValidator } from '../types';
|
|
|
6
7
|
export function RequiredValidator(): FormValidator {
|
|
7
8
|
return function (value) {
|
|
8
9
|
// console.log('RequiredValidator', value, (value == null || value.length === 0) ? { required: true } : null);
|
|
9
|
-
|
|
10
|
+
if (isArray(value) || typeof value === 'string') {
|
|
11
|
+
return (value.length === 0) ? { required: true } : null;
|
|
12
|
+
} else {
|
|
13
|
+
return value == null ? { required: true } : null;
|
|
14
|
+
}
|
|
10
15
|
};
|
|
11
16
|
// return (value == null || value.length === 0) ? 'required' : null;
|
|
12
17
|
}
|
|
@@ -36,17 +36,23 @@ export function useFormBuilder<T, U extends (FormGroup | FormArray)>(
|
|
|
36
36
|
|
|
37
37
|
useEffect(() => {
|
|
38
38
|
const onChange = (value: T) => {
|
|
39
|
+
// console.log('useFormBuilder.onChange', value);
|
|
39
40
|
const newState = { value, flags: collection.state, errors: mapErrors_(collection.errors) };
|
|
40
|
-
// console.log('useFormBuilder.onChange', newState);
|
|
41
41
|
setState(newState);
|
|
42
42
|
};
|
|
43
43
|
collection.on('change', onChange);
|
|
44
|
-
collection.validateAndChange_();
|
|
44
|
+
// collection.validateAndChange_();
|
|
45
|
+
collection.revalidate_();
|
|
46
|
+
// const value = collection.value;
|
|
47
|
+
// collection.reset();
|
|
48
|
+
// collection.patch(value);
|
|
45
49
|
// console.log('subscribe');
|
|
46
50
|
return () => collection.off('change', onChange);
|
|
47
51
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
48
52
|
}, deps);
|
|
49
53
|
|
|
54
|
+
// console.log('useFormBuilder', collection.value);
|
|
55
|
+
|
|
50
56
|
return [state, setValue, setTouched, reset, collection];
|
|
51
57
|
}
|
|
52
58
|
|