@rjsf/core 5.18.4 → 5.18.6
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/dist/core.umd.js +101 -78
- package/dist/index.esm.js +101 -74
- package/dist/index.esm.js.map +3 -3
- package/dist/index.js +101 -74
- package/dist/index.js.map +3 -3
- package/lib/components/Form.d.ts +16 -2
- package/lib/components/Form.js +78 -57
- package/lib/components/Form.js.map +1 -1
- package/lib/components/fields/ArrayField.d.ts +2 -2
- package/lib/components/fields/NumberField.js +1 -1
- package/lib/components/fields/NumberField.js.map +1 -1
- package/lib/components/fields/ObjectField.js +5 -2
- package/lib/components/fields/ObjectField.js.map +1 -1
- package/lib/components/fields/SchemaField.js +4 -3
- package/lib/components/fields/SchemaField.js.map +1 -1
- package/lib/components/templates/BaseInputTemplate.js +2 -2
- package/lib/components/templates/BaseInputTemplate.js.map +1 -1
- package/lib/components/templates/WrapIfAdditionalTemplate.js +1 -1
- package/lib/components/templates/WrapIfAdditionalTemplate.js.map +1 -1
- package/lib/components/widgets/CheckboxesWidget.js +2 -2
- package/lib/components/widgets/CheckboxesWidget.js.map +1 -1
- package/lib/components/widgets/RadioWidget.js +2 -2
- package/lib/components/widgets/RadioWidget.js.map +1 -1
- package/lib/components/widgets/TextareaWidget.js +2 -2
- package/lib/components/widgets/TextareaWidget.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/src/components/Form.tsx +40 -21
- package/src/components/fields/NumberField.tsx +1 -1
- package/src/components/fields/ObjectField.tsx +6 -3
- package/src/components/fields/SchemaField.tsx +3 -3
- package/src/components/templates/BaseInputTemplate.tsx +5 -2
- package/src/components/templates/WrapIfAdditionalTemplate.tsx +1 -1
- package/src/components/widgets/CheckboxesWidget.tsx +4 -4
- package/src/components/widgets/RadioWidget.tsx +4 -4
- package/src/components/widgets/TextareaWidget.tsx +2 -2
package/dist/core.umd.js
CHANGED
|
@@ -1063,7 +1063,7 @@
|
|
|
1063
1063
|
[onChange]
|
|
1064
1064
|
);
|
|
1065
1065
|
if (typeof lastValue === "string" && typeof value === "number") {
|
|
1066
|
-
const re = new RegExp(
|
|
1066
|
+
const re = new RegExp(`^(${String(value).replace(".", "\\.")})?\\.?0*$`);
|
|
1067
1067
|
if (lastValue.match(re)) {
|
|
1068
1068
|
value = lastValue;
|
|
1069
1069
|
}
|
|
@@ -1180,20 +1180,23 @@
|
|
|
1180
1180
|
const { formData, onChange, registry } = this.props;
|
|
1181
1181
|
const newFormData = { ...formData };
|
|
1182
1182
|
let type = void 0;
|
|
1183
|
+
let defaultValue = void 0;
|
|
1183
1184
|
if (isObject(schema.additionalProperties)) {
|
|
1184
1185
|
type = schema.additionalProperties.type;
|
|
1186
|
+
defaultValue = schema.additionalProperties.default;
|
|
1185
1187
|
let apSchema = schema.additionalProperties;
|
|
1186
1188
|
if (utils.REF_KEY in apSchema) {
|
|
1187
1189
|
const { schemaUtils } = registry;
|
|
1188
1190
|
apSchema = schemaUtils.retrieveSchema({ $ref: apSchema[utils.REF_KEY] }, formData);
|
|
1189
1191
|
type = apSchema.type;
|
|
1192
|
+
defaultValue = apSchema.default;
|
|
1190
1193
|
}
|
|
1191
1194
|
if (!type && (utils.ANY_OF_KEY in apSchema || utils.ONE_OF_KEY in apSchema)) {
|
|
1192
1195
|
type = "object";
|
|
1193
1196
|
}
|
|
1194
1197
|
}
|
|
1195
1198
|
const newKey = this.getAvailableKey("newKey", newFormData);
|
|
1196
|
-
set(newFormData, newKey, this.getDefaultValue(type));
|
|
1199
|
+
set(newFormData, newKey, defaultValue ?? this.getDefaultValue(type));
|
|
1197
1200
|
onChange(newFormData);
|
|
1198
1201
|
};
|
|
1199
1202
|
}
|
|
@@ -1241,8 +1244,8 @@
|
|
|
1241
1244
|
idSchema,
|
|
1242
1245
|
name,
|
|
1243
1246
|
required = false,
|
|
1244
|
-
disabled
|
|
1245
|
-
readonly
|
|
1247
|
+
disabled,
|
|
1248
|
+
readonly,
|
|
1246
1249
|
hideError,
|
|
1247
1250
|
idPrefix,
|
|
1248
1251
|
idSeparator,
|
|
@@ -1413,11 +1416,11 @@
|
|
|
1413
1416
|
[fieldId, onChange]
|
|
1414
1417
|
);
|
|
1415
1418
|
const FieldComponent = getFieldComponent(schema, uiOptions, idSchema, registry);
|
|
1416
|
-
const disabled = Boolean(
|
|
1417
|
-
const readonly = Boolean(
|
|
1419
|
+
const disabled = Boolean(uiOptions.disabled ?? props.disabled);
|
|
1420
|
+
const readonly = Boolean(uiOptions.readonly ?? props.readonly ?? props.schema.readOnly ?? schema.readOnly);
|
|
1418
1421
|
const uiSchemaHideError = uiOptions.hideError;
|
|
1419
1422
|
const hideError = uiSchemaHideError === void 0 ? props.hideError : Boolean(uiSchemaHideError);
|
|
1420
|
-
const autofocus = Boolean(
|
|
1423
|
+
const autofocus = Boolean(uiOptions.autofocus ?? props.autofocus);
|
|
1421
1424
|
if (Object.keys(schema).length === 0) {
|
|
1422
1425
|
return null;
|
|
1423
1426
|
}
|
|
@@ -1915,9 +1918,12 @@
|
|
|
1915
1918
|
({ target: { value: value2 } }) => onChange(value2 === "" ? options.emptyValue : value2),
|
|
1916
1919
|
[onChange, options]
|
|
1917
1920
|
);
|
|
1918
|
-
const _onBlur = react.useCallback(
|
|
1921
|
+
const _onBlur = react.useCallback(
|
|
1922
|
+
({ target }) => onBlur(id, target && target.value),
|
|
1923
|
+
[onBlur, id]
|
|
1924
|
+
);
|
|
1919
1925
|
const _onFocus = react.useCallback(
|
|
1920
|
-
({ target
|
|
1926
|
+
({ target }) => onFocus(id, target && target.value),
|
|
1921
1927
|
[onFocus, id]
|
|
1922
1928
|
);
|
|
1923
1929
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -2241,7 +2247,7 @@
|
|
|
2241
2247
|
className: "form-control",
|
|
2242
2248
|
type: "text",
|
|
2243
2249
|
id: `${id}-key`,
|
|
2244
|
-
onBlur: (
|
|
2250
|
+
onBlur: ({ target }) => onKeyChange(target && target.value),
|
|
2245
2251
|
defaultValue: label
|
|
2246
2252
|
}
|
|
2247
2253
|
)
|
|
@@ -2497,11 +2503,11 @@
|
|
|
2497
2503
|
}) {
|
|
2498
2504
|
const checkboxesValues = Array.isArray(value) ? value : [value];
|
|
2499
2505
|
const handleBlur = react.useCallback(
|
|
2500
|
-
({ target
|
|
2506
|
+
({ target }) => onBlur(id, utils.enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)),
|
|
2501
2507
|
[onBlur, id]
|
|
2502
2508
|
);
|
|
2503
2509
|
const handleFocus = react.useCallback(
|
|
2504
|
-
({ target
|
|
2510
|
+
({ target }) => onFocus(id, utils.enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)),
|
|
2505
2511
|
[onFocus, id]
|
|
2506
2512
|
);
|
|
2507
2513
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "checkboxes", id, children: Array.isArray(enumOptions) && enumOptions.map((option, index) => {
|
|
@@ -2744,11 +2750,11 @@
|
|
|
2744
2750
|
}) {
|
|
2745
2751
|
const { enumOptions, enumDisabled, inline, emptyValue } = options;
|
|
2746
2752
|
const handleBlur = react.useCallback(
|
|
2747
|
-
({ target
|
|
2753
|
+
({ target }) => onBlur(id, utils.enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)),
|
|
2748
2754
|
[onBlur, id]
|
|
2749
2755
|
);
|
|
2750
2756
|
const handleFocus = react.useCallback(
|
|
2751
|
-
({ target
|
|
2757
|
+
({ target }) => onFocus(id, utils.enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)),
|
|
2752
2758
|
[onFocus, id]
|
|
2753
2759
|
);
|
|
2754
2760
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "field-radio-group", id, children: Array.isArray(enumOptions) && enumOptions.map((option, i) => {
|
|
@@ -2881,11 +2887,11 @@
|
|
|
2881
2887
|
[onChange, options.emptyValue]
|
|
2882
2888
|
);
|
|
2883
2889
|
const handleBlur = react.useCallback(
|
|
2884
|
-
({ target
|
|
2890
|
+
({ target }) => onBlur(id, target && target.value),
|
|
2885
2891
|
[onBlur, id]
|
|
2886
2892
|
);
|
|
2887
2893
|
const handleFocus = react.useCallback(
|
|
2888
|
-
({ target
|
|
2894
|
+
({ target }) => onFocus(id, target && target.value),
|
|
2889
2895
|
[id, onFocus]
|
|
2890
2896
|
);
|
|
2891
2897
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3024,9 +3030,22 @@
|
|
|
3024
3030
|
};
|
|
3025
3031
|
return getAllPaths(pathSchema);
|
|
3026
3032
|
};
|
|
3033
|
+
/** Returns the `formData` after filtering to remove any extra data not in a form field
|
|
3034
|
+
*
|
|
3035
|
+
* @param formData - The data for the `Form`
|
|
3036
|
+
* @returns The `formData` after omitting extra data
|
|
3037
|
+
*/
|
|
3038
|
+
this.omitExtraData = (formData) => {
|
|
3039
|
+
const { schema, schemaUtils } = this.state;
|
|
3040
|
+
const retrievedSchema = schemaUtils.retrieveSchema(schema, formData);
|
|
3041
|
+
const pathSchema = schemaUtils.toPathSchema(retrievedSchema, "", formData);
|
|
3042
|
+
const fieldNames = this.getFieldNames(pathSchema, formData);
|
|
3043
|
+
const newFormData = this.getUsedFormData(formData, fieldNames);
|
|
3044
|
+
return newFormData;
|
|
3045
|
+
};
|
|
3027
3046
|
/** Function to handle changes made to a field in the `Form`. This handler receives an entirely new copy of the
|
|
3028
3047
|
* `formData` along with a new `ErrorSchema`. It will first update the `formData` with any missing default fields and
|
|
3029
|
-
* then, if `omitExtraData` and `liveOmit` are turned on, the `formData` will be
|
|
3048
|
+
* then, if `omitExtraData` and `liveOmit` are turned on, the `formData` will be filtered to remove any extra data not
|
|
3030
3049
|
* in a form field. Then, the resulting formData will be validated if required. The state will be updated with the new
|
|
3031
3050
|
* updated (potentially filtered) `formData`, any errors that resulted from validation. Finally the `onChange`
|
|
3032
3051
|
* callback will be called if specified with the updated state.
|
|
@@ -3045,12 +3064,8 @@
|
|
|
3045
3064
|
const mustValidate = !noValidate && liveValidate;
|
|
3046
3065
|
let state = { formData, schema };
|
|
3047
3066
|
let newFormData = formData;
|
|
3048
|
-
let _retrievedSchema;
|
|
3049
3067
|
if (omitExtraData === true && liveOmit === true) {
|
|
3050
|
-
|
|
3051
|
-
const pathSchema = schemaUtils.toPathSchema(_retrievedSchema, "", formData);
|
|
3052
|
-
const fieldNames = this.getFieldNames(pathSchema, formData);
|
|
3053
|
-
newFormData = this.getUsedFormData(formData, fieldNames);
|
|
3068
|
+
newFormData = this.omitExtraData(formData);
|
|
3054
3069
|
state = {
|
|
3055
3070
|
formData: newFormData
|
|
3056
3071
|
};
|
|
@@ -3081,9 +3096,6 @@
|
|
|
3081
3096
|
errors: utils.toErrorList(errorSchema)
|
|
3082
3097
|
};
|
|
3083
3098
|
}
|
|
3084
|
-
if (_retrievedSchema) {
|
|
3085
|
-
state.retrievedSchema = _retrievedSchema;
|
|
3086
|
-
}
|
|
3087
3099
|
this.setState(state, () => onChange && onChange({ ...this.state, ...state }, id));
|
|
3088
3100
|
};
|
|
3089
3101
|
/**
|
|
@@ -3145,14 +3157,10 @@
|
|
|
3145
3157
|
event.persist();
|
|
3146
3158
|
const { omitExtraData, extraErrors, noValidate, onSubmit } = this.props;
|
|
3147
3159
|
let { formData: newFormData } = this.state;
|
|
3148
|
-
const { schema, schemaUtils } = this.state;
|
|
3149
3160
|
if (omitExtraData === true) {
|
|
3150
|
-
|
|
3151
|
-
const pathSchema = schemaUtils.toPathSchema(retrievedSchema, "", newFormData);
|
|
3152
|
-
const fieldNames = this.getFieldNames(pathSchema, newFormData);
|
|
3153
|
-
newFormData = this.getUsedFormData(newFormData, fieldNames);
|
|
3161
|
+
newFormData = this.omitExtraData(newFormData);
|
|
3154
3162
|
}
|
|
3155
|
-
if (noValidate || this.
|
|
3163
|
+
if (noValidate || this.validateFormWithFormData(newFormData)) {
|
|
3156
3164
|
const errorSchema = extraErrors || {};
|
|
3157
3165
|
const errors = extraErrors ? utils.toErrorList(extraErrors) : [];
|
|
3158
3166
|
this.setState(
|
|
@@ -3182,6 +3190,59 @@
|
|
|
3182
3190
|
this.formElement.current.requestSubmit();
|
|
3183
3191
|
}
|
|
3184
3192
|
};
|
|
3193
|
+
/** Validates the form using the given `formData`. For use on form submission or on programmatic validation.
|
|
3194
|
+
* If `onError` is provided, then it will be called with the list of errors.
|
|
3195
|
+
*
|
|
3196
|
+
* @param formData - The form data to validate
|
|
3197
|
+
* @returns - True if the form is valid, false otherwise.
|
|
3198
|
+
*/
|
|
3199
|
+
this.validateFormWithFormData = (formData) => {
|
|
3200
|
+
const { extraErrors, extraErrorsBlockSubmit, focusOnFirstError, onError } = this.props;
|
|
3201
|
+
const { errors: prevErrors } = this.state;
|
|
3202
|
+
const schemaValidation = this.validate(formData);
|
|
3203
|
+
let errors = schemaValidation.errors;
|
|
3204
|
+
let errorSchema = schemaValidation.errorSchema;
|
|
3205
|
+
const schemaValidationErrors = errors;
|
|
3206
|
+
const schemaValidationErrorSchema = errorSchema;
|
|
3207
|
+
const hasError = errors.length > 0 || extraErrors && extraErrorsBlockSubmit;
|
|
3208
|
+
if (hasError) {
|
|
3209
|
+
if (extraErrors) {
|
|
3210
|
+
const merged = utils.validationDataMerge(schemaValidation, extraErrors);
|
|
3211
|
+
errorSchema = merged.errorSchema;
|
|
3212
|
+
errors = merged.errors;
|
|
3213
|
+
}
|
|
3214
|
+
if (focusOnFirstError) {
|
|
3215
|
+
if (typeof focusOnFirstError === "function") {
|
|
3216
|
+
focusOnFirstError(errors[0]);
|
|
3217
|
+
} else {
|
|
3218
|
+
this.focusOnError(errors[0]);
|
|
3219
|
+
}
|
|
3220
|
+
}
|
|
3221
|
+
this.setState(
|
|
3222
|
+
{
|
|
3223
|
+
errors,
|
|
3224
|
+
errorSchema,
|
|
3225
|
+
schemaValidationErrors,
|
|
3226
|
+
schemaValidationErrorSchema
|
|
3227
|
+
},
|
|
3228
|
+
() => {
|
|
3229
|
+
if (onError) {
|
|
3230
|
+
onError(errors);
|
|
3231
|
+
} else {
|
|
3232
|
+
console.error("Form validation failed", errors);
|
|
3233
|
+
}
|
|
3234
|
+
}
|
|
3235
|
+
);
|
|
3236
|
+
} else if (prevErrors.length > 0) {
|
|
3237
|
+
this.setState({
|
|
3238
|
+
errors: [],
|
|
3239
|
+
errorSchema: {},
|
|
3240
|
+
schemaValidationErrors: [],
|
|
3241
|
+
schemaValidationErrorSchema: {}
|
|
3242
|
+
});
|
|
3243
|
+
}
|
|
3244
|
+
return !hasError;
|
|
3245
|
+
};
|
|
3185
3246
|
if (!props.validator) {
|
|
3186
3247
|
throw new Error("A validator is required for Form functionality to work");
|
|
3187
3248
|
}
|
|
@@ -3425,57 +3486,19 @@
|
|
|
3425
3486
|
field.focus();
|
|
3426
3487
|
}
|
|
3427
3488
|
}
|
|
3428
|
-
/** Programmatically validate the form.
|
|
3489
|
+
/** Programmatically validate the form. If `omitExtraData` is true, the `formData` will first be filtered to remove
|
|
3490
|
+
* any extra data not in a form field. If `onError` is provided, then it will be called with the list of errors the
|
|
3429
3491
|
* same way as would happen on form submission.
|
|
3430
3492
|
*
|
|
3431
3493
|
* @returns - True if the form is valid, false otherwise.
|
|
3432
3494
|
*/
|
|
3433
3495
|
validateForm() {
|
|
3434
|
-
const {
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
let errorSchema = schemaValidation.errorSchema;
|
|
3439
|
-
const schemaValidationErrors = errors;
|
|
3440
|
-
const schemaValidationErrorSchema = errorSchema;
|
|
3441
|
-
const hasError = errors.length > 0 || extraErrors && extraErrorsBlockSubmit;
|
|
3442
|
-
if (hasError) {
|
|
3443
|
-
if (extraErrors) {
|
|
3444
|
-
const merged = utils.validationDataMerge(schemaValidation, extraErrors);
|
|
3445
|
-
errorSchema = merged.errorSchema;
|
|
3446
|
-
errors = merged.errors;
|
|
3447
|
-
}
|
|
3448
|
-
if (focusOnFirstError) {
|
|
3449
|
-
if (typeof focusOnFirstError === "function") {
|
|
3450
|
-
focusOnFirstError(errors[0]);
|
|
3451
|
-
} else {
|
|
3452
|
-
this.focusOnError(errors[0]);
|
|
3453
|
-
}
|
|
3454
|
-
}
|
|
3455
|
-
this.setState(
|
|
3456
|
-
{
|
|
3457
|
-
errors,
|
|
3458
|
-
errorSchema,
|
|
3459
|
-
schemaValidationErrors,
|
|
3460
|
-
schemaValidationErrorSchema
|
|
3461
|
-
},
|
|
3462
|
-
() => {
|
|
3463
|
-
if (onError) {
|
|
3464
|
-
onError(errors);
|
|
3465
|
-
} else {
|
|
3466
|
-
console.error("Form validation failed", errors);
|
|
3467
|
-
}
|
|
3468
|
-
}
|
|
3469
|
-
);
|
|
3470
|
-
} else if (prevErrors.length > 0) {
|
|
3471
|
-
this.setState({
|
|
3472
|
-
errors: [],
|
|
3473
|
-
errorSchema: {},
|
|
3474
|
-
schemaValidationErrors: [],
|
|
3475
|
-
schemaValidationErrorSchema: {}
|
|
3476
|
-
});
|
|
3496
|
+
const { omitExtraData } = this.props;
|
|
3497
|
+
let { formData: newFormData } = this.state;
|
|
3498
|
+
if (omitExtraData === true) {
|
|
3499
|
+
newFormData = this.omitExtraData(newFormData);
|
|
3477
3500
|
}
|
|
3478
|
-
return
|
|
3501
|
+
return this.validateFormWithFormData(newFormData);
|
|
3479
3502
|
}
|
|
3480
3503
|
/** Renders the `Form` fields inside the <form> | `tagName` or `_internalFormWrapper`, rendering any errors if
|
|
3481
3504
|
* needed along with the submit button or any children of the form.
|
|
@@ -3497,8 +3520,8 @@
|
|
|
3497
3520
|
acceptcharset,
|
|
3498
3521
|
acceptCharset,
|
|
3499
3522
|
noHtml5Validate = false,
|
|
3500
|
-
disabled
|
|
3501
|
-
readonly
|
|
3523
|
+
disabled,
|
|
3524
|
+
readonly,
|
|
3502
3525
|
formContext,
|
|
3503
3526
|
showErrorList = "top",
|
|
3504
3527
|
_internalFormWrapper
|
package/dist/index.esm.js
CHANGED
|
@@ -1134,7 +1134,7 @@ function NumberField(props) {
|
|
|
1134
1134
|
[onChange]
|
|
1135
1135
|
);
|
|
1136
1136
|
if (typeof lastValue === "string" && typeof value === "number") {
|
|
1137
|
-
const re = new RegExp(
|
|
1137
|
+
const re = new RegExp(`^(${String(value).replace(".", "\\.")})?\\.?0*$`);
|
|
1138
1138
|
if (lastValue.match(re)) {
|
|
1139
1139
|
value = lastValue;
|
|
1140
1140
|
}
|
|
@@ -1272,20 +1272,23 @@ var ObjectField = class extends Component3 {
|
|
|
1272
1272
|
const { formData, onChange, registry } = this.props;
|
|
1273
1273
|
const newFormData = { ...formData };
|
|
1274
1274
|
let type = void 0;
|
|
1275
|
+
let defaultValue = void 0;
|
|
1275
1276
|
if (isObject3(schema.additionalProperties)) {
|
|
1276
1277
|
type = schema.additionalProperties.type;
|
|
1278
|
+
defaultValue = schema.additionalProperties.default;
|
|
1277
1279
|
let apSchema = schema.additionalProperties;
|
|
1278
1280
|
if (REF_KEY in apSchema) {
|
|
1279
1281
|
const { schemaUtils } = registry;
|
|
1280
1282
|
apSchema = schemaUtils.retrieveSchema({ $ref: apSchema[REF_KEY] }, formData);
|
|
1281
1283
|
type = apSchema.type;
|
|
1284
|
+
defaultValue = apSchema.default;
|
|
1282
1285
|
}
|
|
1283
1286
|
if (!type && (ANY_OF_KEY2 in apSchema || ONE_OF_KEY2 in apSchema)) {
|
|
1284
1287
|
type = "object";
|
|
1285
1288
|
}
|
|
1286
1289
|
}
|
|
1287
1290
|
const newKey = this.getAvailableKey("newKey", newFormData);
|
|
1288
|
-
set2(newFormData, newKey, this.getDefaultValue(type));
|
|
1291
|
+
set2(newFormData, newKey, defaultValue ?? this.getDefaultValue(type));
|
|
1289
1292
|
onChange(newFormData);
|
|
1290
1293
|
};
|
|
1291
1294
|
}
|
|
@@ -1333,8 +1336,8 @@ var ObjectField = class extends Component3 {
|
|
|
1333
1336
|
idSchema,
|
|
1334
1337
|
name,
|
|
1335
1338
|
required = false,
|
|
1336
|
-
disabled
|
|
1337
|
-
readonly
|
|
1339
|
+
disabled,
|
|
1340
|
+
readonly,
|
|
1338
1341
|
hideError,
|
|
1339
1342
|
idPrefix,
|
|
1340
1343
|
idSeparator,
|
|
@@ -1524,11 +1527,11 @@ function SchemaFieldRender(props) {
|
|
|
1524
1527
|
[fieldId, onChange]
|
|
1525
1528
|
);
|
|
1526
1529
|
const FieldComponent = getFieldComponent(schema, uiOptions, idSchema, registry);
|
|
1527
|
-
const disabled = Boolean(
|
|
1528
|
-
const readonly = Boolean(
|
|
1530
|
+
const disabled = Boolean(uiOptions.disabled ?? props.disabled);
|
|
1531
|
+
const readonly = Boolean(uiOptions.readonly ?? props.readonly ?? props.schema.readOnly ?? schema.readOnly);
|
|
1529
1532
|
const uiSchemaHideError = uiOptions.hideError;
|
|
1530
1533
|
const hideError = uiSchemaHideError === void 0 ? props.hideError : Boolean(uiSchemaHideError);
|
|
1531
|
-
const autofocus = Boolean(
|
|
1534
|
+
const autofocus = Boolean(uiOptions.autofocus ?? props.autofocus);
|
|
1532
1535
|
if (Object.keys(schema).length === 0) {
|
|
1533
1536
|
return null;
|
|
1534
1537
|
}
|
|
@@ -2073,9 +2076,12 @@ function BaseInputTemplate(props) {
|
|
|
2073
2076
|
({ target: { value: value2 } }) => onChange(value2 === "" ? options.emptyValue : value2),
|
|
2074
2077
|
[onChange, options]
|
|
2075
2078
|
);
|
|
2076
|
-
const _onBlur = useCallback3(
|
|
2079
|
+
const _onBlur = useCallback3(
|
|
2080
|
+
({ target }) => onBlur(id, target && target.value),
|
|
2081
|
+
[onBlur, id]
|
|
2082
|
+
);
|
|
2077
2083
|
const _onFocus = useCallback3(
|
|
2078
|
-
({ target
|
|
2084
|
+
({ target }) => onFocus(id, target && target.value),
|
|
2079
2085
|
[onFocus, id]
|
|
2080
2086
|
);
|
|
2081
2087
|
return /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
@@ -2467,7 +2473,7 @@ function WrapIfAdditionalTemplate(props) {
|
|
|
2467
2473
|
className: "form-control",
|
|
2468
2474
|
type: "text",
|
|
2469
2475
|
id: `${id}-key`,
|
|
2470
|
-
onBlur: (
|
|
2476
|
+
onBlur: ({ target }) => onKeyChange(target && target.value),
|
|
2471
2477
|
defaultValue: label
|
|
2472
2478
|
}
|
|
2473
2479
|
)
|
|
@@ -2761,11 +2767,11 @@ function CheckboxesWidget({
|
|
|
2761
2767
|
}) {
|
|
2762
2768
|
const checkboxesValues = Array.isArray(value) ? value : [value];
|
|
2763
2769
|
const handleBlur = useCallback6(
|
|
2764
|
-
({ target
|
|
2770
|
+
({ target }) => onBlur(id, enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)),
|
|
2765
2771
|
[onBlur, id]
|
|
2766
2772
|
);
|
|
2767
2773
|
const handleFocus = useCallback6(
|
|
2768
|
-
({ target
|
|
2774
|
+
({ target }) => onFocus(id, enumOptionsValueForIndex(target && target.value, enumOptions, emptyValue)),
|
|
2769
2775
|
[onFocus, id]
|
|
2770
2776
|
);
|
|
2771
2777
|
return /* @__PURE__ */ jsx29("div", { className: "checkboxes", id, children: Array.isArray(enumOptions) && enumOptions.map((option, index) => {
|
|
@@ -3056,11 +3062,11 @@ function RadioWidget({
|
|
|
3056
3062
|
}) {
|
|
3057
3063
|
const { enumOptions, enumDisabled, inline, emptyValue } = options;
|
|
3058
3064
|
const handleBlur = useCallback9(
|
|
3059
|
-
({ target
|
|
3065
|
+
({ target }) => onBlur(id, enumOptionsValueForIndex2(target && target.value, enumOptions, emptyValue)),
|
|
3060
3066
|
[onBlur, id]
|
|
3061
3067
|
);
|
|
3062
3068
|
const handleFocus = useCallback9(
|
|
3063
|
-
({ target
|
|
3069
|
+
({ target }) => onFocus(id, enumOptionsValueForIndex2(target && target.value, enumOptions, emptyValue)),
|
|
3064
3070
|
[onFocus, id]
|
|
3065
3071
|
);
|
|
3066
3072
|
return /* @__PURE__ */ jsx37("div", { className: "field-radio-group", id, children: Array.isArray(enumOptions) && enumOptions.map((option, i) => {
|
|
@@ -3210,11 +3216,11 @@ function TextareaWidget({
|
|
|
3210
3216
|
[onChange, options.emptyValue]
|
|
3211
3217
|
);
|
|
3212
3218
|
const handleBlur = useCallback11(
|
|
3213
|
-
({ target
|
|
3219
|
+
({ target }) => onBlur(id, target && target.value),
|
|
3214
3220
|
[onBlur, id]
|
|
3215
3221
|
);
|
|
3216
3222
|
const handleFocus = useCallback11(
|
|
3217
|
-
({ target
|
|
3223
|
+
({ target }) => onFocus(id, target && target.value),
|
|
3218
3224
|
[id, onFocus]
|
|
3219
3225
|
);
|
|
3220
3226
|
return /* @__PURE__ */ jsx40(
|
|
@@ -3373,9 +3379,22 @@ var Form = class extends Component5 {
|
|
|
3373
3379
|
};
|
|
3374
3380
|
return getAllPaths(pathSchema);
|
|
3375
3381
|
};
|
|
3382
|
+
/** Returns the `formData` after filtering to remove any extra data not in a form field
|
|
3383
|
+
*
|
|
3384
|
+
* @param formData - The data for the `Form`
|
|
3385
|
+
* @returns The `formData` after omitting extra data
|
|
3386
|
+
*/
|
|
3387
|
+
this.omitExtraData = (formData) => {
|
|
3388
|
+
const { schema, schemaUtils } = this.state;
|
|
3389
|
+
const retrievedSchema = schemaUtils.retrieveSchema(schema, formData);
|
|
3390
|
+
const pathSchema = schemaUtils.toPathSchema(retrievedSchema, "", formData);
|
|
3391
|
+
const fieldNames = this.getFieldNames(pathSchema, formData);
|
|
3392
|
+
const newFormData = this.getUsedFormData(formData, fieldNames);
|
|
3393
|
+
return newFormData;
|
|
3394
|
+
};
|
|
3376
3395
|
/** Function to handle changes made to a field in the `Form`. This handler receives an entirely new copy of the
|
|
3377
3396
|
* `formData` along with a new `ErrorSchema`. It will first update the `formData` with any missing default fields and
|
|
3378
|
-
* then, if `omitExtraData` and `liveOmit` are turned on, the `formData` will be
|
|
3397
|
+
* then, if `omitExtraData` and `liveOmit` are turned on, the `formData` will be filtered to remove any extra data not
|
|
3379
3398
|
* in a form field. Then, the resulting formData will be validated if required. The state will be updated with the new
|
|
3380
3399
|
* updated (potentially filtered) `formData`, any errors that resulted from validation. Finally the `onChange`
|
|
3381
3400
|
* callback will be called if specified with the updated state.
|
|
@@ -3396,10 +3415,7 @@ var Form = class extends Component5 {
|
|
|
3396
3415
|
let newFormData = formData;
|
|
3397
3416
|
let _retrievedSchema;
|
|
3398
3417
|
if (omitExtraData === true && liveOmit === true) {
|
|
3399
|
-
|
|
3400
|
-
const pathSchema = schemaUtils.toPathSchema(_retrievedSchema, "", formData);
|
|
3401
|
-
const fieldNames = this.getFieldNames(pathSchema, formData);
|
|
3402
|
-
newFormData = this.getUsedFormData(formData, fieldNames);
|
|
3418
|
+
newFormData = this.omitExtraData(formData);
|
|
3403
3419
|
state = {
|
|
3404
3420
|
formData: newFormData
|
|
3405
3421
|
};
|
|
@@ -3494,14 +3510,10 @@ var Form = class extends Component5 {
|
|
|
3494
3510
|
event.persist();
|
|
3495
3511
|
const { omitExtraData, extraErrors, noValidate, onSubmit } = this.props;
|
|
3496
3512
|
let { formData: newFormData } = this.state;
|
|
3497
|
-
const { schema, schemaUtils } = this.state;
|
|
3498
3513
|
if (omitExtraData === true) {
|
|
3499
|
-
|
|
3500
|
-
const pathSchema = schemaUtils.toPathSchema(retrievedSchema, "", newFormData);
|
|
3501
|
-
const fieldNames = this.getFieldNames(pathSchema, newFormData);
|
|
3502
|
-
newFormData = this.getUsedFormData(newFormData, fieldNames);
|
|
3514
|
+
newFormData = this.omitExtraData(newFormData);
|
|
3503
3515
|
}
|
|
3504
|
-
if (noValidate || this.
|
|
3516
|
+
if (noValidate || this.validateFormWithFormData(newFormData)) {
|
|
3505
3517
|
const errorSchema = extraErrors || {};
|
|
3506
3518
|
const errors = extraErrors ? toErrorList(extraErrors) : [];
|
|
3507
3519
|
this.setState(
|
|
@@ -3531,6 +3543,59 @@ var Form = class extends Component5 {
|
|
|
3531
3543
|
this.formElement.current.requestSubmit();
|
|
3532
3544
|
}
|
|
3533
3545
|
};
|
|
3546
|
+
/** Validates the form using the given `formData`. For use on form submission or on programmatic validation.
|
|
3547
|
+
* If `onError` is provided, then it will be called with the list of errors.
|
|
3548
|
+
*
|
|
3549
|
+
* @param formData - The form data to validate
|
|
3550
|
+
* @returns - True if the form is valid, false otherwise.
|
|
3551
|
+
*/
|
|
3552
|
+
this.validateFormWithFormData = (formData) => {
|
|
3553
|
+
const { extraErrors, extraErrorsBlockSubmit, focusOnFirstError, onError } = this.props;
|
|
3554
|
+
const { errors: prevErrors } = this.state;
|
|
3555
|
+
const schemaValidation = this.validate(formData);
|
|
3556
|
+
let errors = schemaValidation.errors;
|
|
3557
|
+
let errorSchema = schemaValidation.errorSchema;
|
|
3558
|
+
const schemaValidationErrors = errors;
|
|
3559
|
+
const schemaValidationErrorSchema = errorSchema;
|
|
3560
|
+
const hasError = errors.length > 0 || extraErrors && extraErrorsBlockSubmit;
|
|
3561
|
+
if (hasError) {
|
|
3562
|
+
if (extraErrors) {
|
|
3563
|
+
const merged = validationDataMerge(schemaValidation, extraErrors);
|
|
3564
|
+
errorSchema = merged.errorSchema;
|
|
3565
|
+
errors = merged.errors;
|
|
3566
|
+
}
|
|
3567
|
+
if (focusOnFirstError) {
|
|
3568
|
+
if (typeof focusOnFirstError === "function") {
|
|
3569
|
+
focusOnFirstError(errors[0]);
|
|
3570
|
+
} else {
|
|
3571
|
+
this.focusOnError(errors[0]);
|
|
3572
|
+
}
|
|
3573
|
+
}
|
|
3574
|
+
this.setState(
|
|
3575
|
+
{
|
|
3576
|
+
errors,
|
|
3577
|
+
errorSchema,
|
|
3578
|
+
schemaValidationErrors,
|
|
3579
|
+
schemaValidationErrorSchema
|
|
3580
|
+
},
|
|
3581
|
+
() => {
|
|
3582
|
+
if (onError) {
|
|
3583
|
+
onError(errors);
|
|
3584
|
+
} else {
|
|
3585
|
+
console.error("Form validation failed", errors);
|
|
3586
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
);
|
|
3589
|
+
} else if (prevErrors.length > 0) {
|
|
3590
|
+
this.setState({
|
|
3591
|
+
errors: [],
|
|
3592
|
+
errorSchema: {},
|
|
3593
|
+
schemaValidationErrors: [],
|
|
3594
|
+
schemaValidationErrorSchema: {}
|
|
3595
|
+
});
|
|
3596
|
+
}
|
|
3597
|
+
return !hasError;
|
|
3598
|
+
};
|
|
3534
3599
|
if (!props.validator) {
|
|
3535
3600
|
throw new Error("A validator is required for Form functionality to work");
|
|
3536
3601
|
}
|
|
@@ -3774,57 +3839,19 @@ var Form = class extends Component5 {
|
|
|
3774
3839
|
field.focus();
|
|
3775
3840
|
}
|
|
3776
3841
|
}
|
|
3777
|
-
/** Programmatically validate the form.
|
|
3842
|
+
/** Programmatically validate the form. If `omitExtraData` is true, the `formData` will first be filtered to remove
|
|
3843
|
+
* any extra data not in a form field. If `onError` is provided, then it will be called with the list of errors the
|
|
3778
3844
|
* same way as would happen on form submission.
|
|
3779
3845
|
*
|
|
3780
3846
|
* @returns - True if the form is valid, false otherwise.
|
|
3781
3847
|
*/
|
|
3782
3848
|
validateForm() {
|
|
3783
|
-
const {
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
let errorSchema = schemaValidation.errorSchema;
|
|
3788
|
-
const schemaValidationErrors = errors;
|
|
3789
|
-
const schemaValidationErrorSchema = errorSchema;
|
|
3790
|
-
const hasError = errors.length > 0 || extraErrors && extraErrorsBlockSubmit;
|
|
3791
|
-
if (hasError) {
|
|
3792
|
-
if (extraErrors) {
|
|
3793
|
-
const merged = validationDataMerge(schemaValidation, extraErrors);
|
|
3794
|
-
errorSchema = merged.errorSchema;
|
|
3795
|
-
errors = merged.errors;
|
|
3796
|
-
}
|
|
3797
|
-
if (focusOnFirstError) {
|
|
3798
|
-
if (typeof focusOnFirstError === "function") {
|
|
3799
|
-
focusOnFirstError(errors[0]);
|
|
3800
|
-
} else {
|
|
3801
|
-
this.focusOnError(errors[0]);
|
|
3802
|
-
}
|
|
3803
|
-
}
|
|
3804
|
-
this.setState(
|
|
3805
|
-
{
|
|
3806
|
-
errors,
|
|
3807
|
-
errorSchema,
|
|
3808
|
-
schemaValidationErrors,
|
|
3809
|
-
schemaValidationErrorSchema
|
|
3810
|
-
},
|
|
3811
|
-
() => {
|
|
3812
|
-
if (onError) {
|
|
3813
|
-
onError(errors);
|
|
3814
|
-
} else {
|
|
3815
|
-
console.error("Form validation failed", errors);
|
|
3816
|
-
}
|
|
3817
|
-
}
|
|
3818
|
-
);
|
|
3819
|
-
} else if (prevErrors.length > 0) {
|
|
3820
|
-
this.setState({
|
|
3821
|
-
errors: [],
|
|
3822
|
-
errorSchema: {},
|
|
3823
|
-
schemaValidationErrors: [],
|
|
3824
|
-
schemaValidationErrorSchema: {}
|
|
3825
|
-
});
|
|
3849
|
+
const { omitExtraData } = this.props;
|
|
3850
|
+
let { formData: newFormData } = this.state;
|
|
3851
|
+
if (omitExtraData === true) {
|
|
3852
|
+
newFormData = this.omitExtraData(newFormData);
|
|
3826
3853
|
}
|
|
3827
|
-
return
|
|
3854
|
+
return this.validateFormWithFormData(newFormData);
|
|
3828
3855
|
}
|
|
3829
3856
|
/** Renders the `Form` fields inside the <form> | `tagName` or `_internalFormWrapper`, rendering any errors if
|
|
3830
3857
|
* needed along with the submit button or any children of the form.
|
|
@@ -3846,8 +3873,8 @@ var Form = class extends Component5 {
|
|
|
3846
3873
|
acceptcharset,
|
|
3847
3874
|
acceptCharset,
|
|
3848
3875
|
noHtml5Validate = false,
|
|
3849
|
-
disabled
|
|
3850
|
-
readonly
|
|
3876
|
+
disabled,
|
|
3877
|
+
readonly,
|
|
3851
3878
|
formContext,
|
|
3852
3879
|
showErrorList = "top",
|
|
3853
3880
|
_internalFormWrapper
|