coles-solid-library 0.3.6 → 0.3.7
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.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FormGroupData, ValidationDefault } from "./formHelp/models";
|
|
1
|
+
import { FormGroupData, ValidationDefault, ValidatorResult, ControlMeta } from "./formHelp/models";
|
|
2
2
|
export { FormArray } from "./formHelp/formArray";
|
|
3
3
|
export { Validators } from "./formHelp/validators";
|
|
4
4
|
/**
|
|
@@ -11,6 +11,7 @@ export declare class FormGroup<T extends object> {
|
|
|
11
11
|
private internalDataSignal;
|
|
12
12
|
private validators;
|
|
13
13
|
private errors;
|
|
14
|
+
private meta;
|
|
14
15
|
private keys;
|
|
15
16
|
constructor(data: FormGroupData<T>);
|
|
16
17
|
/**
|
|
@@ -70,6 +71,12 @@ export declare class FormGroup<T extends object> {
|
|
|
70
71
|
* @param hasError - Whether the error should be set or cleared
|
|
71
72
|
*/
|
|
72
73
|
setError(key: keyof T, errKey: string, hasError: boolean): void;
|
|
74
|
+
addValidator<K extends keyof T>(key: K, validator: ValidatorResult<T[K]>): void;
|
|
75
|
+
removeValidator<K extends keyof T>(key: K, errKey: string): void;
|
|
76
|
+
getMeta<K extends keyof T>(key: K): ControlMeta<T[K]>;
|
|
77
|
+
markTouched<K extends keyof T>(key: K): void;
|
|
78
|
+
markDirty<K extends keyof T>(key: K): void;
|
|
79
|
+
reset(): void;
|
|
73
80
|
/**
|
|
74
81
|
* Sets a new value for a specified form control.
|
|
75
82
|
*
|
|
@@ -101,6 +108,7 @@ export declare class FormGroup<T extends object> {
|
|
|
101
108
|
* @returns `true` if the control(s) pass all validations; otherwise, `false`.
|
|
102
109
|
*/
|
|
103
110
|
validate<K extends keyof T>(key?: K): boolean;
|
|
111
|
+
validateAsync<K extends keyof T>(key?: K): Promise<boolean>;
|
|
104
112
|
}
|
|
105
113
|
/**
|
|
106
114
|
* Utility type to extract the element type from an array type
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { JSX } from "solid-js";
|
|
2
2
|
import { FormArray } from "./formArray";
|
|
3
3
|
export interface ValidatorResult<T> {
|
|
4
|
-
revalidate: (val: T) => boolean;
|
|
5
4
|
errKey: string;
|
|
5
|
+
revalidate: (val: T) => boolean | Promise<boolean>;
|
|
6
|
+
hide?: (val: T) => boolean;
|
|
6
7
|
}
|
|
7
8
|
export interface Error {
|
|
8
9
|
key: string;
|
|
@@ -14,18 +15,14 @@ export type ErrorObject<T> = {
|
|
|
14
15
|
[P in keyof T]: Error[];
|
|
15
16
|
};
|
|
16
17
|
export type ArrayValidation<T> = [(ValidationDefault<T, keyof T>)[], ValidatorResult<T[]>[]];
|
|
17
|
-
export interface ValidatorResult<T> {
|
|
18
|
-
revalidate: (val: T) => boolean;
|
|
19
|
-
errKey: string;
|
|
20
|
-
hide?: (val: T) => boolean;
|
|
21
|
-
}
|
|
22
|
-
export interface Error {
|
|
23
|
-
key: string;
|
|
24
|
-
hasError: boolean;
|
|
25
|
-
}
|
|
26
18
|
export type ValidatorObject<T> = {
|
|
27
19
|
[P in keyof T]?: ValidatorResult<T[P]>[];
|
|
28
20
|
};
|
|
29
21
|
export type FormGroupData<T extends object> = {
|
|
30
|
-
[P in keyof T]: [T[P], ValidatorResult<T[P]>[]] | (T[P] extends object ? FormArray<T[P]> : any);
|
|
22
|
+
[P in keyof T]: [T[P], ValidatorResult<T[P]>[]] | (T[P] extends (infer U)[] ? FormArray<U & object> : T[P] extends object ? FormArray<T[P] & object> : any);
|
|
31
23
|
};
|
|
24
|
+
export interface ControlMeta<T = any> {
|
|
25
|
+
touched: boolean;
|
|
26
|
+
dirty: boolean;
|
|
27
|
+
initialValue: T;
|
|
28
|
+
}
|
|
@@ -67,6 +67,10 @@ export declare class Validators {
|
|
|
67
67
|
* @returns A ValidatorResult that includes the error key and a revalidation function.
|
|
68
68
|
*/
|
|
69
69
|
static custom<T>(errKey: string, validator: (value: T) => boolean, hide?: (val: T) => boolean): ValidatorResult<T>;
|
|
70
|
+
/**
|
|
71
|
+
* Creates an async validator; resolves promise to boolean.
|
|
72
|
+
*/
|
|
73
|
+
static asyncCustom<T>(errKey: string, validator: (value: T) => Promise<boolean>, hide?: (val: T) => boolean): ValidatorResult<T>;
|
|
70
74
|
/**
|
|
71
75
|
* A helper function that creates a ValidatorResult object.
|
|
72
76
|
*
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Accessor } from 'solid-js';
|
|
2
|
+
export interface FieldBinding<T, K extends keyof T> {
|
|
3
|
+
value: Accessor<T[K]>;
|
|
4
|
+
setValue: (v: T[K]) => void;
|
|
5
|
+
errors: () => {
|
|
6
|
+
key: string;
|
|
7
|
+
hasError: boolean;
|
|
8
|
+
}[];
|
|
9
|
+
hasError: () => boolean;
|
|
10
|
+
touched: () => boolean;
|
|
11
|
+
dirty: () => boolean;
|
|
12
|
+
validate: () => boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function useFormFieldBinding<T extends object, K extends keyof T>(key: K): FieldBinding<T, K>;
|
package/dist/index.esm.js
CHANGED
|
@@ -1400,10 +1400,13 @@ const useFormContext = () => {
|
|
|
1400
1400
|
};
|
|
1401
1401
|
const Form = props => {
|
|
1402
1402
|
const startData = props.data.get() ?? {};
|
|
1403
|
+
// Custom shallow clone preserving FormArray instances (already handled in FormGroup.get)
|
|
1404
|
+
const initialValue = {};
|
|
1405
|
+
Object.keys(startData).forEach(k => {
|
|
1406
|
+
initialValue[k] = startData[k];
|
|
1407
|
+
});
|
|
1403
1408
|
return createComponent(Provider, {
|
|
1404
|
-
|
|
1405
|
-
return CloneStore(startData);
|
|
1406
|
-
},
|
|
1409
|
+
value: initialValue,
|
|
1407
1410
|
get formGroup() {
|
|
1408
1411
|
return props.data;
|
|
1409
1412
|
},
|
|
@@ -1498,21 +1501,21 @@ const Input = props => {
|
|
|
1498
1501
|
}
|
|
1499
1502
|
if (props.onChange) props.onChange(e);
|
|
1500
1503
|
};
|
|
1501
|
-
|
|
1502
|
-
if (isRequired()) {
|
|
1503
|
-
context?.setName?.(old => `${old} *`);
|
|
1504
|
-
} else {
|
|
1505
|
-
context?.setName?.(old => old);
|
|
1506
|
-
}
|
|
1507
|
-
});
|
|
1504
|
+
// Removed name mutation adding '*' to avoid duplicating required indicator; legend handles display.
|
|
1508
1505
|
onMount(() => {
|
|
1509
1506
|
if (!isNullish(context.getName)) {
|
|
1510
1507
|
// Force a non-checkbox field type
|
|
1511
1508
|
context.setFieldType(props.type === "checkbox" ? "text" : props.type ?? "text");
|
|
1512
1509
|
if (!isNullish(formContext?.data)) {
|
|
1513
|
-
const
|
|
1514
|
-
if (
|
|
1515
|
-
|
|
1510
|
+
const raw = formContext.data[context.formName ?? ""];
|
|
1511
|
+
if (typeof raw === 'string') {
|
|
1512
|
+
const formValue = raw.trim();
|
|
1513
|
+
if (formValue) {
|
|
1514
|
+
context.setValue(formValue);
|
|
1515
|
+
context.setTextInside(true);
|
|
1516
|
+
}
|
|
1517
|
+
} else if (raw !== undefined && raw !== null) {
|
|
1518
|
+
context.setValue(raw);
|
|
1516
1519
|
context.setTextInside(true);
|
|
1517
1520
|
}
|
|
1518
1521
|
}
|
|
@@ -2122,7 +2125,6 @@ function Select(props) {
|
|
|
2122
2125
|
selectStyle: currStyle
|
|
2123
2126
|
}));
|
|
2124
2127
|
const [dropTop, setDropTop] = createSignal(false);
|
|
2125
|
-
console.log("Select rendered with options:", options);
|
|
2126
2128
|
return (() => {
|
|
2127
2129
|
var _el$7 = _tmpl$5$1(),
|
|
2128
2130
|
_el$8 = _el$7.firstChild,
|
|
@@ -2299,7 +2301,6 @@ function Option(props) {
|
|
|
2299
2301
|
const contextSuccess = selectFormContextValue(props.value);
|
|
2300
2302
|
!contextSuccess ? selectFormFieldValue(props.value) : true;
|
|
2301
2303
|
if (!formField?.getName?.()) {
|
|
2302
|
-
console.log('selected!', props.value, select);
|
|
2303
2304
|
select.selectValue?.(props.value);
|
|
2304
2305
|
formField?.setFocused?.(true);
|
|
2305
2306
|
}
|
|
@@ -2406,7 +2407,7 @@ const TextArea = props => {
|
|
|
2406
2407
|
if (!!context?.getName && !!e.currentTarget.value.trim()) {
|
|
2407
2408
|
context?.setValue(e.currentTarget.value);
|
|
2408
2409
|
context?.setTextInside(true);
|
|
2409
|
-
} else if (!!context
|
|
2410
|
+
} else if (!!context?.getName && !e.currentTarget.value.trim()) {
|
|
2410
2411
|
context?.setValue("");
|
|
2411
2412
|
context?.setTextInside(false);
|
|
2412
2413
|
}
|
|
@@ -3000,11 +3001,21 @@ function RadioGroup(props) {
|
|
|
3000
3001
|
radioGroupCount++;
|
|
3001
3002
|
const groupName = props.name ?? `radio-group-${radioGroupCount}`;
|
|
3002
3003
|
const [internalValue, setInternalValue] = createSignal(props.defaultValue);
|
|
3004
|
+
const formField = useFormProvider();
|
|
3005
|
+
const formContext = useFormContext();
|
|
3003
3006
|
const selectedValue = () => props.value !== undefined ? props.value : internalValue();
|
|
3004
3007
|
const setSelectedValue = val => {
|
|
3005
3008
|
if (props.value === undefined) {
|
|
3006
3009
|
setInternalValue(val);
|
|
3007
3010
|
}
|
|
3011
|
+
// Bridge to FormGroup if inside a FormField with formName
|
|
3012
|
+
if (formField?.formName && formContext?.formGroup?.set) {
|
|
3013
|
+
formContext.formGroup.set(formField.formName, val);
|
|
3014
|
+
formContext.setData(old => ({
|
|
3015
|
+
...old,
|
|
3016
|
+
[formField.formName]: val
|
|
3017
|
+
}));
|
|
3018
|
+
}
|
|
3008
3019
|
props.onChange?.(val);
|
|
3009
3020
|
};
|
|
3010
3021
|
const radioRefs = [];
|
|
@@ -3450,39 +3461,47 @@ class FormArray {
|
|
|
3450
3461
|
}
|
|
3451
3462
|
// Validate all controls in the form array.
|
|
3452
3463
|
if (isNullish(index)) {
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
}
|
|
3462
|
-
this.errors =
|
|
3463
|
-
const
|
|
3464
|
+
// Always evaluate array-level validators even if the array is empty
|
|
3465
|
+
const arrayLevelErrors = this.internalArrayValidation.map(validator => ({
|
|
3466
|
+
key: validator.errKey,
|
|
3467
|
+
hasError: !validator.revalidate(values)
|
|
3468
|
+
}));
|
|
3469
|
+
if (values.length === 0) {
|
|
3470
|
+
this.errors = [arrayLevelErrors]; // store array-level errors at index 0 placeholder
|
|
3471
|
+
return this.errors.flat().every(error => !error.hasError);
|
|
3472
|
+
}
|
|
3473
|
+
this.errors = values.map((value, i) => {
|
|
3474
|
+
const controlErrors = this.internalValidation.map(([propKey, validators]) => {
|
|
3475
|
+
const currentVal = value[propKey];
|
|
3464
3476
|
return validators.map(validator => ({
|
|
3465
3477
|
key: validator.errKey,
|
|
3466
|
-
hasError: !validator.revalidate(
|
|
3478
|
+
hasError: !validator.revalidate(currentVal)
|
|
3467
3479
|
}));
|
|
3468
3480
|
});
|
|
3469
3481
|
const arrayErrors = this.internalArrayValidation.map(validator => ({
|
|
3470
3482
|
key: validator.errKey,
|
|
3471
3483
|
hasError: !validator.revalidate(values)
|
|
3472
3484
|
}));
|
|
3473
|
-
|
|
3474
|
-
|
|
3485
|
+
const merged = [...controlErrors.flat(), ...arrayErrors];
|
|
3486
|
+
this.errors[i] = merged;
|
|
3487
|
+
return merged;
|
|
3475
3488
|
});
|
|
3476
3489
|
return this.errors.flat().every(error => !error.hasError);
|
|
3477
3490
|
}
|
|
3478
3491
|
// Validate a specific control in the form array.
|
|
3479
|
-
const
|
|
3492
|
+
const value = values[index];
|
|
3493
|
+
const controlErrors = this.internalValidation.map(([propKey, validators]) => {
|
|
3494
|
+
const currentVal = value[propKey];
|
|
3480
3495
|
return validators.map(validator => ({
|
|
3481
3496
|
key: validator.errKey,
|
|
3482
|
-
hasError: !validator.revalidate(
|
|
3497
|
+
hasError: !validator.revalidate(currentVal)
|
|
3483
3498
|
}));
|
|
3484
3499
|
});
|
|
3485
|
-
|
|
3500
|
+
const arrayErrors = this.internalArrayValidation.map(validator => ({
|
|
3501
|
+
key: validator.errKey,
|
|
3502
|
+
hasError: !validator.revalidate(values)
|
|
3503
|
+
}));
|
|
3504
|
+
this.errors[index] = [...controlErrors.flat(), ...arrayErrors];
|
|
3486
3505
|
return this.errors[index].every(error => !error.hasError);
|
|
3487
3506
|
}
|
|
3488
3507
|
}
|
|
@@ -3529,15 +3548,16 @@ const FormField2 = props => {
|
|
|
3529
3548
|
});
|
|
3530
3549
|
const theChildren = children(() => props.children);
|
|
3531
3550
|
const formErrors = () => {
|
|
3532
|
-
|
|
3551
|
+
if (!local?.formName) return [];
|
|
3552
|
+
const allErrors = (formContext?.formGroup.getErrors(local.formName) ?? []).filter(e => e.hasError);
|
|
3533
3553
|
if (allErrors.length === 0) return [];
|
|
3534
|
-
let errKeys = allErrors.map(
|
|
3535
|
-
// test just require
|
|
3554
|
+
let errKeys = allErrors.map(e => e.key);
|
|
3536
3555
|
if (errKeys.includes('required')) {
|
|
3537
|
-
errKeys = errKeys.filter(
|
|
3556
|
+
errKeys = errKeys.filter(k => k !== 'minLength' && k !== 'maxLength');
|
|
3538
3557
|
}
|
|
3539
|
-
|
|
3540
|
-
|
|
3558
|
+
// Map to displays stored in context errors (ColeError registered displays) if available
|
|
3559
|
+
const displayMap = context?.getErrors?.().err ?? [];
|
|
3560
|
+
return displayMap.filter(e => errKeys.includes(e.key));
|
|
3541
3561
|
};
|
|
3542
3562
|
const hasRequired = createMemo(() => {
|
|
3543
3563
|
if (isNullish(local?.formName)) return false;
|
|
@@ -3746,7 +3766,13 @@ class Validators {
|
|
|
3746
3766
|
* @returns A ValidatorResult that includes the error key and a revalidation function.
|
|
3747
3767
|
*/
|
|
3748
3768
|
static custom(errKey, validator, hide) {
|
|
3749
|
-
return this.createValidatorResult(errKey, validator);
|
|
3769
|
+
return this.createValidatorResult(errKey, validator, hide);
|
|
3770
|
+
}
|
|
3771
|
+
/**
|
|
3772
|
+
* Creates an async validator; resolves promise to boolean.
|
|
3773
|
+
*/
|
|
3774
|
+
static asyncCustom(errKey, validator, hide) {
|
|
3775
|
+
return this.createValidatorResult(errKey, validator, hide);
|
|
3750
3776
|
}
|
|
3751
3777
|
/**
|
|
3752
3778
|
* A helper function that creates a ValidatorResult object.
|
|
@@ -3777,6 +3803,7 @@ class FormGroup {
|
|
|
3777
3803
|
internalDataSignal;
|
|
3778
3804
|
validators = {};
|
|
3779
3805
|
errors;
|
|
3806
|
+
meta = {};
|
|
3780
3807
|
keys = [];
|
|
3781
3808
|
constructor(data) {
|
|
3782
3809
|
this.data = data;
|
|
@@ -3787,11 +3814,8 @@ class FormGroup {
|
|
|
3787
3814
|
const value = data[key];
|
|
3788
3815
|
this.keys.push(key);
|
|
3789
3816
|
if (value instanceof FormArray) {
|
|
3790
|
-
|
|
3791
|
-
// We need to ensure that when T[key] is an array type, we store the array returned by FormArray
|
|
3792
|
-
newData[key] = value.get();
|
|
3817
|
+
newData[key] = value;
|
|
3793
3818
|
} else {
|
|
3794
|
-
// Otherwise, initialize the data, validators, and errors for the control.
|
|
3795
3819
|
newData[key] = value[0];
|
|
3796
3820
|
newValidators[key] = value[1];
|
|
3797
3821
|
newErrors[key] = value[1].map(validator => ({
|
|
@@ -3799,13 +3823,31 @@ class FormGroup {
|
|
|
3799
3823
|
hasError: false
|
|
3800
3824
|
}));
|
|
3801
3825
|
}
|
|
3826
|
+
const initialVal = value instanceof FormArray ? value.get() : CloneStore(newData[key]);
|
|
3827
|
+
this.meta[key] = {
|
|
3828
|
+
touched: false,
|
|
3829
|
+
dirty: false,
|
|
3830
|
+
initialValue: initialVal
|
|
3831
|
+
};
|
|
3802
3832
|
}
|
|
3803
3833
|
this.internalDataSignal = createStore(newData);
|
|
3804
3834
|
this.validators = newValidators;
|
|
3805
3835
|
this.errors = createSignal(newErrors);
|
|
3806
3836
|
}
|
|
3807
3837
|
get(key) {
|
|
3808
|
-
if (!key)
|
|
3838
|
+
if (!key) {
|
|
3839
|
+
// Custom clone that preserves FormArray instances (structuredClone fails on functions inside)
|
|
3840
|
+
const clone = {};
|
|
3841
|
+
for (const k of this.keys) {
|
|
3842
|
+
const val = this.internalDataSignal[0][k];
|
|
3843
|
+
if (val instanceof FormArray) {
|
|
3844
|
+
clone[k] = val; // keep reference; consumer methods operate on instance
|
|
3845
|
+
} else {
|
|
3846
|
+
clone[k] = CloneStore(val);
|
|
3847
|
+
}
|
|
3848
|
+
}
|
|
3849
|
+
return clone;
|
|
3850
|
+
}
|
|
3809
3851
|
// If the control is a FormArray, use its get method
|
|
3810
3852
|
if (this.internalDataSignal[0][key] instanceof FormArray) {
|
|
3811
3853
|
// Return the array from FormArray.get() as the expected type T[K]
|
|
@@ -3885,16 +3927,56 @@ class FormGroup {
|
|
|
3885
3927
|
* @param hasError - Whether the error should be set or cleared
|
|
3886
3928
|
*/
|
|
3887
3929
|
setError(key, errKey, hasError) {
|
|
3888
|
-
if (this.internalDataSignal[0][key] instanceof FormArray)
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
return Clone(old);
|
|
3930
|
+
if (this.internalDataSignal[0][key] instanceof FormArray) return;
|
|
3931
|
+
const current = this.errors[0]();
|
|
3932
|
+
const list = current[key] ?? [];
|
|
3933
|
+
let index = list.findIndex(e => e.key === errKey);
|
|
3934
|
+
if (index === -1) {
|
|
3935
|
+
list.push({
|
|
3936
|
+
key: errKey,
|
|
3937
|
+
hasError
|
|
3897
3938
|
});
|
|
3939
|
+
} else {
|
|
3940
|
+
list[index].hasError = hasError;
|
|
3941
|
+
}
|
|
3942
|
+
current[key] = list;
|
|
3943
|
+
this.errors[1](() => Clone(current));
|
|
3944
|
+
}
|
|
3945
|
+
addValidator(key, validator) {
|
|
3946
|
+
if (!this.validators[key]) this.validators[key] = [];
|
|
3947
|
+
this.validators[key].push(validator);
|
|
3948
|
+
this.setError(key, validator.errKey, false);
|
|
3949
|
+
}
|
|
3950
|
+
removeValidator(key, errKey) {
|
|
3951
|
+
if (!this.validators[key]) return;
|
|
3952
|
+
this.validators[key] = this.validators[key].filter(v => v.errKey !== errKey);
|
|
3953
|
+
const current = this.errors[0]();
|
|
3954
|
+
if (current[key]) {
|
|
3955
|
+
current[key] = current[key].filter(e => e.key !== errKey);
|
|
3956
|
+
this.errors[1](() => Clone(current));
|
|
3957
|
+
}
|
|
3958
|
+
}
|
|
3959
|
+
getMeta(key) {
|
|
3960
|
+
return this.meta[key];
|
|
3961
|
+
}
|
|
3962
|
+
markTouched(key) {
|
|
3963
|
+
this.meta[key].touched = true;
|
|
3964
|
+
}
|
|
3965
|
+
markDirty(key) {
|
|
3966
|
+
this.meta[key].dirty = true;
|
|
3967
|
+
}
|
|
3968
|
+
reset() {
|
|
3969
|
+
for (const k of this.keys) {
|
|
3970
|
+
const m = this.meta[k];
|
|
3971
|
+
this.set(k, CloneStore(m.initialValue));
|
|
3972
|
+
m.touched = false;
|
|
3973
|
+
m.dirty = false;
|
|
3974
|
+
const errs = this.errors[0]();
|
|
3975
|
+
errs[k] = errs[k]?.map(e => ({
|
|
3976
|
+
...e,
|
|
3977
|
+
hasError: false
|
|
3978
|
+
}));
|
|
3979
|
+
this.errors[1](() => Clone(errs));
|
|
3898
3980
|
}
|
|
3899
3981
|
}
|
|
3900
3982
|
/**
|
|
@@ -3915,6 +3997,11 @@ class FormGroup {
|
|
|
3915
3997
|
...old,
|
|
3916
3998
|
[key]: value
|
|
3917
3999
|
}));
|
|
4000
|
+
const m = this.meta[key];
|
|
4001
|
+
if (m) {
|
|
4002
|
+
if (!m.touched) m.touched = true;
|
|
4003
|
+
if (!m.dirty && JSON.stringify(m.initialValue) !== JSON.stringify(value)) m.dirty = true;
|
|
4004
|
+
}
|
|
3918
4005
|
}
|
|
3919
4006
|
/**
|
|
3920
4007
|
* Adds an item to a FormArray control
|
|
@@ -3949,28 +4036,62 @@ class FormGroup {
|
|
|
3949
4036
|
*/
|
|
3950
4037
|
validate(key) {
|
|
3951
4038
|
if (isNullish(this.internalDataSignal?.[0])) {
|
|
3952
|
-
console.error('Data is null');
|
|
4039
|
+
if (process?.env?.NODE_ENV !== 'production') console.error('Data is null');
|
|
3953
4040
|
return false;
|
|
3954
4041
|
}
|
|
3955
4042
|
if (!key) {
|
|
3956
4043
|
const results = this.keys.map(k => this.validate(k));
|
|
3957
|
-
return results.every(
|
|
4044
|
+
return results.every(Boolean);
|
|
3958
4045
|
}
|
|
3959
4046
|
if (this.internalDataSignal?.[0]?.[key] instanceof FormArray) {
|
|
3960
4047
|
return this.internalDataSignal[0][key].validateCurrent();
|
|
3961
4048
|
}
|
|
3962
4049
|
const validators = this.validators[key];
|
|
3963
4050
|
if (!validators) return true;
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
4051
|
+
let allValid = true;
|
|
4052
|
+
for (const validator of validators) {
|
|
4053
|
+
try {
|
|
4054
|
+
const result = validator.revalidate(this.internalDataSignal[0][key]);
|
|
4055
|
+
const isPromise = typeof result?.then === 'function';
|
|
4056
|
+
const resolved = isPromise ? true : result; // optimistic until async handled via validateAsync
|
|
4057
|
+
const toHide = validator.hide?.(this.internalDataSignal[0][key]);
|
|
4058
|
+
if (toHide) {
|
|
4059
|
+
this.setError(key, validator.errKey, false);
|
|
4060
|
+
} else {
|
|
4061
|
+
this.setError(key, validator.errKey, !resolved);
|
|
4062
|
+
if (!resolved) allValid = false;
|
|
4063
|
+
}
|
|
4064
|
+
} catch (e) {
|
|
4065
|
+
if (process?.env?.NODE_ENV !== 'production') console.warn('Validator threw', validator.errKey, e);
|
|
4066
|
+
this.setError(key, validator.errKey, true);
|
|
4067
|
+
allValid = false;
|
|
3970
4068
|
}
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
4069
|
+
}
|
|
4070
|
+
return allValid;
|
|
4071
|
+
}
|
|
4072
|
+
async validateAsync(key) {
|
|
4073
|
+
if (!key) {
|
|
4074
|
+
const results = await Promise.all(this.keys.map(k => this.validateAsync(k)));
|
|
4075
|
+
return results.every(Boolean);
|
|
4076
|
+
}
|
|
4077
|
+
if (this.internalDataSignal?.[0]?.[key] instanceof FormArray) {
|
|
4078
|
+
return this.internalDataSignal[0][key].validateCurrent();
|
|
4079
|
+
}
|
|
4080
|
+
const validators = this.validators[key];
|
|
4081
|
+
if (!validators) return true;
|
|
4082
|
+
let allValid = true;
|
|
4083
|
+
for (const validator of validators) {
|
|
4084
|
+
try {
|
|
4085
|
+
const res = await validator.revalidate(this.internalDataSignal[0][key]);
|
|
4086
|
+
const toHide = validator.hide?.(this.internalDataSignal[0][key]);
|
|
4087
|
+
if (toHide) this.setError(key, validator.errKey, false);else this.setError(key, validator.errKey, !res);
|
|
4088
|
+
if (!res && !toHide) allValid = false;
|
|
4089
|
+
} catch {
|
|
4090
|
+
this.setError(key, validator.errKey, true);
|
|
4091
|
+
allValid = false;
|
|
4092
|
+
}
|
|
4093
|
+
}
|
|
4094
|
+
return allValid;
|
|
3974
4095
|
}
|
|
3975
4096
|
}
|
|
3976
4097
|
|