vee-validate 4.5.11 → 4.6.0
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/README.md +38 -22
- package/dist/vee-validate.d.ts +545 -290
- package/dist/vee-validate.esm.js +196 -87
- package/dist/vee-validate.js +192 -85
- package/dist/vee-validate.min.js +2 -2
- package/package.json +3 -3
- package/CHANGELOG.md +0 -912
package/dist/vee-validate.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* vee-validate v4.
|
|
2
|
+
* vee-validate v4.6.0
|
|
3
3
|
* (c) 2022 Abdelrahman Awad
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
@@ -56,18 +56,6 @@
|
|
|
56
56
|
function isLocator(value) {
|
|
57
57
|
return isCallable(value) && !!value.__locatorRef;
|
|
58
58
|
}
|
|
59
|
-
/**
|
|
60
|
-
* Checks if an tag name is a native HTML tag and not a Vue component
|
|
61
|
-
*/
|
|
62
|
-
function isHTMLTag(tag) {
|
|
63
|
-
return ['input', 'textarea', 'select'].includes(tag);
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Checks if an input is of type file
|
|
67
|
-
*/
|
|
68
|
-
function isFileInputNode(tag, attrs) {
|
|
69
|
-
return isHTMLTag(tag) && attrs.type === 'file';
|
|
70
|
-
}
|
|
71
59
|
function isYupValidator(value) {
|
|
72
60
|
return !!value && isCallable(value.validate);
|
|
73
61
|
}
|
|
@@ -120,7 +108,7 @@
|
|
|
120
108
|
* For multi-selects because the value binding will reset the value
|
|
121
109
|
*/
|
|
122
110
|
function shouldHaveValueBinding(tag, attrs) {
|
|
123
|
-
return isNativeMultiSelectNode(tag, attrs)
|
|
111
|
+
return !isNativeMultiSelectNode(tag, attrs) && attrs.type !== 'file' && !hasCheckedAttr(attrs.type);
|
|
124
112
|
}
|
|
125
113
|
function isFormSubmitEvent(evt) {
|
|
126
114
|
return isEvent(evt) && evt.target && 'submit' in evt.target;
|
|
@@ -286,6 +274,15 @@
|
|
|
286
274
|
}, ms);
|
|
287
275
|
return new Promise(resolve => resolves.push(resolve));
|
|
288
276
|
};
|
|
277
|
+
}
|
|
278
|
+
function applyModelModifiers(value, modifiers) {
|
|
279
|
+
if (!isObject(modifiers)) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
if (modifiers.number) {
|
|
283
|
+
return toNumber(value);
|
|
284
|
+
}
|
|
285
|
+
return value;
|
|
289
286
|
}
|
|
290
287
|
|
|
291
288
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -329,7 +326,8 @@
|
|
|
329
326
|
return getBoundValue(input);
|
|
330
327
|
}
|
|
331
328
|
if (input.type === 'file' && input.files) {
|
|
332
|
-
|
|
329
|
+
const files = Array.from(input.files);
|
|
330
|
+
return input.multiple ? files : files[0];
|
|
333
331
|
}
|
|
334
332
|
if (isNativeMultiSelect(input)) {
|
|
335
333
|
return Array.from(input.options)
|
|
@@ -828,8 +826,8 @@
|
|
|
828
826
|
/**
|
|
829
827
|
* Creates the field value and resolves the initial value
|
|
830
828
|
*/
|
|
831
|
-
function _useFieldValue(path, modelValue, shouldInjectForm) {
|
|
832
|
-
const form = shouldInjectForm ? injectWithSelf(FormContextKey, undefined) : undefined;
|
|
829
|
+
function _useFieldValue(path, modelValue, shouldInjectForm = true) {
|
|
830
|
+
const form = shouldInjectForm === true ? injectWithSelf(FormContextKey, undefined) : undefined;
|
|
833
831
|
const modelRef = vue.ref(vue.unref(modelValue));
|
|
834
832
|
function resolveInitialValue() {
|
|
835
833
|
if (!form) {
|
|
@@ -859,7 +857,7 @@
|
|
|
859
857
|
// prioritize model value over form values
|
|
860
858
|
// #3429
|
|
861
859
|
const currentValue = modelValue ? vue.unref(modelValue) : getFromPath(form.values, vue.unref(path), vue.unref(initialValue));
|
|
862
|
-
form.stageInitialValue(vue.unref(path), currentValue);
|
|
860
|
+
form.stageInitialValue(vue.unref(path), currentValue, true);
|
|
863
861
|
// otherwise use a computed setter that triggers the `setFieldValue`
|
|
864
862
|
const value = vue.computed({
|
|
865
863
|
get() {
|
|
@@ -938,7 +936,7 @@
|
|
|
938
936
|
return _useField(name, rules, opts);
|
|
939
937
|
}
|
|
940
938
|
function _useField(name, rules, opts) {
|
|
941
|
-
const { initialValue: modelValue, validateOnMount, bails, type, checkedValue, label, validateOnValueUpdate, uncheckedValue, standalone, } = normalizeOptions(vue.unref(name), opts);
|
|
939
|
+
const { initialValue: modelValue, validateOnMount, bails, type, checkedValue, label, validateOnValueUpdate, uncheckedValue, standalone, keepValueOnUnmount, modelPropName, syncVModel, } = normalizeOptions(vue.unref(name), opts);
|
|
942
940
|
const form = !standalone ? injectWithSelf(FormContextKey) : undefined;
|
|
943
941
|
// a flag indicating if the field is about to be removed/unmounted.
|
|
944
942
|
let markedForRemoval = false;
|
|
@@ -946,6 +944,9 @@
|
|
|
946
944
|
modelValue,
|
|
947
945
|
standalone,
|
|
948
946
|
});
|
|
947
|
+
if (syncVModel) {
|
|
948
|
+
useVModel({ value, prop: modelPropName, handleChange });
|
|
949
|
+
}
|
|
949
950
|
/**
|
|
950
951
|
* Handles common onBlur meta update
|
|
951
952
|
*/
|
|
@@ -1004,13 +1005,13 @@
|
|
|
1004
1005
|
return validateValidStateOnly();
|
|
1005
1006
|
}
|
|
1006
1007
|
// Common input/change event handler
|
|
1007
|
-
|
|
1008
|
+
function handleChange(e, shouldValidate = true) {
|
|
1008
1009
|
const newValue = normalizeEventValue(e);
|
|
1009
1010
|
value.value = newValue;
|
|
1010
1011
|
if (!validateOnValueUpdate && shouldValidate) {
|
|
1011
1012
|
validateWithStateMutation();
|
|
1012
1013
|
}
|
|
1013
|
-
}
|
|
1014
|
+
}
|
|
1014
1015
|
// Runs the initial validation
|
|
1015
1016
|
vue.onMounted(() => {
|
|
1016
1017
|
if (validateOnMount) {
|
|
@@ -1027,7 +1028,13 @@
|
|
|
1027
1028
|
}
|
|
1028
1029
|
let unwatchValue;
|
|
1029
1030
|
function watchValue() {
|
|
1030
|
-
unwatchValue = vue.watch(value,
|
|
1031
|
+
unwatchValue = vue.watch(value, (val, oldVal) => {
|
|
1032
|
+
if (es6(val, oldVal)) {
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
1035
|
+
const validateFn = validateOnValueUpdate ? validateWithStateMutation : validateValidStateOnly;
|
|
1036
|
+
validateFn();
|
|
1037
|
+
}, {
|
|
1031
1038
|
deep: true,
|
|
1032
1039
|
});
|
|
1033
1040
|
}
|
|
@@ -1068,6 +1075,7 @@
|
|
|
1068
1075
|
checkedValue,
|
|
1069
1076
|
uncheckedValue,
|
|
1070
1077
|
bails,
|
|
1078
|
+
keepValueOnUnmount,
|
|
1071
1079
|
resetField,
|
|
1072
1080
|
handleReset: () => resetField(),
|
|
1073
1081
|
validate: validate$1,
|
|
@@ -1145,6 +1153,9 @@
|
|
|
1145
1153
|
label: name,
|
|
1146
1154
|
validateOnValueUpdate: true,
|
|
1147
1155
|
standalone: false,
|
|
1156
|
+
keepValueOnUnmount: undefined,
|
|
1157
|
+
modelPropName: 'modelValue',
|
|
1158
|
+
syncVModel: true,
|
|
1148
1159
|
});
|
|
1149
1160
|
if (!opts) {
|
|
1150
1161
|
return defaults();
|
|
@@ -1176,8 +1187,8 @@
|
|
|
1176
1187
|
return Array.isArray(currentValue) ? currentValue.includes(checkedVal) : checkedVal === currentValue;
|
|
1177
1188
|
});
|
|
1178
1189
|
function handleCheckboxChange(e, shouldValidate = true) {
|
|
1179
|
-
var _a
|
|
1180
|
-
if (checked.value === ((
|
|
1190
|
+
var _a;
|
|
1191
|
+
if (checked.value === ((_a = e === null || e === void 0 ? void 0 : e.target) === null || _a === void 0 ? void 0 : _a.checked)) {
|
|
1181
1192
|
return;
|
|
1182
1193
|
}
|
|
1183
1194
|
let newValue = normalizeEventValue(e);
|
|
@@ -1188,8 +1199,10 @@
|
|
|
1188
1199
|
handleChange(newValue, shouldValidate);
|
|
1189
1200
|
}
|
|
1190
1201
|
vue.onBeforeUnmount(() => {
|
|
1191
|
-
|
|
1192
|
-
|
|
1202
|
+
var _a, _b;
|
|
1203
|
+
const shouldKeepValue = (_b = (_a = vue.unref(field.keepValueOnUnmount)) !== null && _a !== void 0 ? _a : vue.unref(form === null || form === void 0 ? void 0 : form.keepValuesOnUnmount)) !== null && _b !== void 0 ? _b : false;
|
|
1204
|
+
// toggles the checkbox value if it was checked and the unset behavior is set
|
|
1205
|
+
if (checked.value && !shouldKeepValue) {
|
|
1193
1206
|
handleCheckboxChange(vue.unref(checkedValue), false);
|
|
1194
1207
|
}
|
|
1195
1208
|
});
|
|
@@ -1198,6 +1211,38 @@
|
|
|
1198
1211
|
uncheckedValue, handleChange: handleCheckboxChange });
|
|
1199
1212
|
}
|
|
1200
1213
|
return patchCheckboxApi(_useField(name, rules, opts));
|
|
1214
|
+
}
|
|
1215
|
+
function useVModel({ prop, value, handleChange }) {
|
|
1216
|
+
const vm = vue.getCurrentInstance();
|
|
1217
|
+
/* istanbul ignore next */
|
|
1218
|
+
if (!vm) {
|
|
1219
|
+
return;
|
|
1220
|
+
}
|
|
1221
|
+
const propName = prop || 'modelValue';
|
|
1222
|
+
const emitName = `update:${propName}`;
|
|
1223
|
+
// Component doesn't have a model prop setup (must be defined on the props)
|
|
1224
|
+
if (!(propName in vm.props)) {
|
|
1225
|
+
return;
|
|
1226
|
+
}
|
|
1227
|
+
vue.watch(value, newValue => {
|
|
1228
|
+
if (es6(newValue, getCurrentModelValue(vm, propName))) {
|
|
1229
|
+
return;
|
|
1230
|
+
}
|
|
1231
|
+
vm.emit(emitName, newValue);
|
|
1232
|
+
});
|
|
1233
|
+
vue.watch(() => getCurrentModelValue(vm, propName), propValue => {
|
|
1234
|
+
if (propValue === IS_ABSENT && value.value === undefined) {
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1237
|
+
const newValue = propValue === IS_ABSENT ? undefined : propValue;
|
|
1238
|
+
if (es6(newValue, applyModelModifiers(value.value, vm.props.modelModifiers))) {
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1241
|
+
handleChange(newValue);
|
|
1242
|
+
});
|
|
1243
|
+
}
|
|
1244
|
+
function getCurrentModelValue(vm, propName) {
|
|
1245
|
+
return vm.props[propName];
|
|
1201
1246
|
}
|
|
1202
1247
|
|
|
1203
1248
|
const FieldImpl = vue.defineComponent({
|
|
@@ -1264,13 +1309,17 @@
|
|
|
1264
1309
|
type: Boolean,
|
|
1265
1310
|
default: false,
|
|
1266
1311
|
},
|
|
1312
|
+
keepValue: {
|
|
1313
|
+
type: Boolean,
|
|
1314
|
+
default: undefined,
|
|
1315
|
+
},
|
|
1267
1316
|
},
|
|
1268
1317
|
setup(props, ctx) {
|
|
1269
1318
|
const rules = vue.toRef(props, 'rules');
|
|
1270
1319
|
const name = vue.toRef(props, 'name');
|
|
1271
1320
|
const label = vue.toRef(props, 'label');
|
|
1272
1321
|
const uncheckedValue = vue.toRef(props, 'uncheckedValue');
|
|
1273
|
-
const
|
|
1322
|
+
const keepValue = vue.toRef(props, 'keepValue');
|
|
1274
1323
|
const { errors, value, errorMessage, validate: validateField, handleChange, handleBlur, setTouched, resetField, handleReset, meta, checked, setErrors, } = useField(name, rules, {
|
|
1275
1324
|
validateOnMount: props.validateOnMount,
|
|
1276
1325
|
bails: props.bails,
|
|
@@ -1282,25 +1331,22 @@
|
|
|
1282
1331
|
uncheckedValue,
|
|
1283
1332
|
label,
|
|
1284
1333
|
validateOnValueUpdate: false,
|
|
1334
|
+
keepValueOnUnmount: keepValue,
|
|
1285
1335
|
});
|
|
1286
1336
|
// If there is a v-model applied on the component we need to emit the `update:modelValue` whenever the value binding changes
|
|
1287
|
-
const onChangeHandler =
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
}
|
|
1292
|
-
: handleChange;
|
|
1337
|
+
const onChangeHandler = function handleChangeWithModel(e, shouldValidate = true) {
|
|
1338
|
+
handleChange(e, shouldValidate);
|
|
1339
|
+
ctx.emit('update:modelValue', value.value);
|
|
1340
|
+
};
|
|
1293
1341
|
const handleInput = (e) => {
|
|
1294
1342
|
if (!hasCheckedAttr(ctx.attrs.type)) {
|
|
1295
1343
|
value.value = normalizeEventValue(e);
|
|
1296
1344
|
}
|
|
1297
1345
|
};
|
|
1298
|
-
const onInputHandler =
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
}
|
|
1303
|
-
: handleInput;
|
|
1346
|
+
const onInputHandler = function handleInputWithModel(e) {
|
|
1347
|
+
handleInput(e);
|
|
1348
|
+
ctx.emit('update:modelValue', value.value);
|
|
1349
|
+
};
|
|
1304
1350
|
const fieldProps = vue.computed(() => {
|
|
1305
1351
|
const { validateOnInput, validateOnChange, validateOnBlur, validateOnModelUpdate } = resolveValidationTriggers(props);
|
|
1306
1352
|
const baseOnBlur = [handleBlur, ctx.attrs.onBlur, validateOnBlur ? validateField : undefined].filter(Boolean);
|
|
@@ -1316,26 +1362,12 @@
|
|
|
1316
1362
|
if (hasCheckedAttr(ctx.attrs.type) && checked) {
|
|
1317
1363
|
attrs.checked = checked.value;
|
|
1318
1364
|
}
|
|
1319
|
-
else {
|
|
1320
|
-
attrs.value = value.value;
|
|
1321
|
-
}
|
|
1322
1365
|
const tag = resolveTag(props, ctx);
|
|
1323
1366
|
if (shouldHaveValueBinding(tag, ctx.attrs)) {
|
|
1324
|
-
|
|
1367
|
+
attrs.value = value.value;
|
|
1325
1368
|
}
|
|
1326
1369
|
return attrs;
|
|
1327
1370
|
});
|
|
1328
|
-
const modelValue = vue.toRef(props, 'modelValue');
|
|
1329
|
-
vue.watch(modelValue, newModelValue => {
|
|
1330
|
-
// Don't attempt to sync absent values
|
|
1331
|
-
if (newModelValue === IS_ABSENT && value.value === undefined) {
|
|
1332
|
-
return;
|
|
1333
|
-
}
|
|
1334
|
-
if (newModelValue !== applyModifiers(value.value, props.modelModifiers)) {
|
|
1335
|
-
value.value = newModelValue === IS_ABSENT ? undefined : newModelValue;
|
|
1336
|
-
validateField();
|
|
1337
|
-
}
|
|
1338
|
-
});
|
|
1339
1371
|
function slotProps() {
|
|
1340
1372
|
return {
|
|
1341
1373
|
field: fieldProps.value,
|
|
@@ -1387,12 +1419,6 @@
|
|
|
1387
1419
|
validateOnModelUpdate: (_d = props.validateOnModelUpdate) !== null && _d !== void 0 ? _d : validateOnModelUpdate,
|
|
1388
1420
|
};
|
|
1389
1421
|
}
|
|
1390
|
-
function applyModifiers(value, modifiers) {
|
|
1391
|
-
if (modifiers.number) {
|
|
1392
|
-
return toNumber(value);
|
|
1393
|
-
}
|
|
1394
|
-
return value;
|
|
1395
|
-
}
|
|
1396
1422
|
function resolveInitialValue(props, ctx) {
|
|
1397
1423
|
// Gets the initial value either from `value` prop/attr or `v-model` binding (modelValue)
|
|
1398
1424
|
// For checkboxes and radio buttons it will always be the model value not the `value` attribute
|
|
@@ -1405,6 +1431,7 @@
|
|
|
1405
1431
|
|
|
1406
1432
|
let FORM_COUNTER = 0;
|
|
1407
1433
|
function useForm(opts) {
|
|
1434
|
+
var _a;
|
|
1408
1435
|
const formId = FORM_COUNTER++;
|
|
1409
1436
|
// Prevents fields from double resetting their values, which causes checkboxes to toggle their initial value
|
|
1410
1437
|
// TODO: This won't be needed if we centralize all the state inside the `form` for form inputs
|
|
@@ -1415,8 +1442,8 @@
|
|
|
1415
1442
|
const isSubmitting = vue.ref(false);
|
|
1416
1443
|
// The number of times the user tried to submit the form
|
|
1417
1444
|
const submitCount = vue.ref(0);
|
|
1418
|
-
//
|
|
1419
|
-
const
|
|
1445
|
+
// field arrays managed by this form
|
|
1446
|
+
const fieldArrays = [];
|
|
1420
1447
|
// a private ref for all form values
|
|
1421
1448
|
const formValues = vue.reactive(klona(vue.unref(opts === null || opts === void 0 ? void 0 : opts.initialValues) || {}));
|
|
1422
1449
|
// the source of errors for the form fields
|
|
@@ -1463,10 +1490,11 @@
|
|
|
1463
1490
|
// mutable non-reactive reference to initial errors
|
|
1464
1491
|
// we need this to process initial errors then unset them
|
|
1465
1492
|
const initialErrors = Object.assign({}, ((opts === null || opts === void 0 ? void 0 : opts.initialErrors) || {}));
|
|
1493
|
+
const keepValuesOnUnmount = (_a = opts === null || opts === void 0 ? void 0 : opts.keepValuesOnUnmount) !== null && _a !== void 0 ? _a : false;
|
|
1466
1494
|
// initial form values
|
|
1467
1495
|
const { initialValues, originalInitialValues, setInitialValues } = useFormInitialValues(fieldsByPath, formValues, opts === null || opts === void 0 ? void 0 : opts.initialValues);
|
|
1468
1496
|
// form meta aggregations
|
|
1469
|
-
const meta = useFormMeta(fieldsByPath, formValues,
|
|
1497
|
+
const meta = useFormMeta(fieldsByPath, formValues, originalInitialValues, errors);
|
|
1470
1498
|
const schema = opts === null || opts === void 0 ? void 0 : opts.validationSchema;
|
|
1471
1499
|
const formCtx = {
|
|
1472
1500
|
formId,
|
|
@@ -1478,7 +1506,8 @@
|
|
|
1478
1506
|
submitCount,
|
|
1479
1507
|
meta,
|
|
1480
1508
|
isSubmitting,
|
|
1481
|
-
|
|
1509
|
+
fieldArrays,
|
|
1510
|
+
keepValuesOnUnmount,
|
|
1482
1511
|
validateSchema: vue.unref(schema) ? validateSchema : undefined,
|
|
1483
1512
|
validate,
|
|
1484
1513
|
register: registerField,
|
|
@@ -1496,6 +1525,7 @@
|
|
|
1496
1525
|
stageInitialValue,
|
|
1497
1526
|
unsetInitialValue,
|
|
1498
1527
|
setFieldInitialValue,
|
|
1528
|
+
useFieldModel,
|
|
1499
1529
|
};
|
|
1500
1530
|
function isFieldGroup(fieldOrGroup) {
|
|
1501
1531
|
return Array.isArray(fieldOrGroup);
|
|
@@ -1565,7 +1595,22 @@
|
|
|
1565
1595
|
setFieldValue(path, fields[path]);
|
|
1566
1596
|
});
|
|
1567
1597
|
// regenerate the arrays when the form values change
|
|
1568
|
-
|
|
1598
|
+
fieldArrays.forEach(f => f && f.reset());
|
|
1599
|
+
}
|
|
1600
|
+
function createModel(path) {
|
|
1601
|
+
const { value } = _useFieldValue(path);
|
|
1602
|
+
vue.watch(value, () => {
|
|
1603
|
+
if (!fieldExists(vue.unref(path))) {
|
|
1604
|
+
validate({ mode: 'validated-only' });
|
|
1605
|
+
}
|
|
1606
|
+
});
|
|
1607
|
+
return value;
|
|
1608
|
+
}
|
|
1609
|
+
function useFieldModel(path) {
|
|
1610
|
+
if (!Array.isArray(path)) {
|
|
1611
|
+
return createModel(path);
|
|
1612
|
+
}
|
|
1613
|
+
return path.map(createModel);
|
|
1569
1614
|
}
|
|
1570
1615
|
/**
|
|
1571
1616
|
* Sets the touched meta state on a field
|
|
@@ -1689,13 +1734,26 @@
|
|
|
1689
1734
|
}
|
|
1690
1735
|
function unregisterField(field) {
|
|
1691
1736
|
const fieldName = vue.unref(field.name);
|
|
1737
|
+
const fieldInstance = fieldsByPath.value[fieldName];
|
|
1738
|
+
const isGroup = !!fieldInstance && isFieldGroup(fieldInstance);
|
|
1692
1739
|
removeFieldFromPath(field, fieldName);
|
|
1693
1740
|
vue.nextTick(() => {
|
|
1741
|
+
var _a;
|
|
1694
1742
|
// clears a field error on unmounted
|
|
1695
1743
|
// we wait till next tick to make sure if the field is completely removed and doesn't have any siblings like checkboxes
|
|
1696
1744
|
// #3384
|
|
1697
1745
|
if (!fieldExists(fieldName)) {
|
|
1698
1746
|
setFieldError(fieldName, undefined);
|
|
1747
|
+
// Checks if the field was configured to be unset during unmount or not
|
|
1748
|
+
// Checks both the form-level config and field-level one
|
|
1749
|
+
// Field has the priority if it is set, otherwise it goes to the form settings
|
|
1750
|
+
const shouldKeepValue = (_a = vue.unref(field.keepValueOnUnmount)) !== null && _a !== void 0 ? _a : vue.unref(keepValuesOnUnmount);
|
|
1751
|
+
if (shouldKeepValue) {
|
|
1752
|
+
return;
|
|
1753
|
+
}
|
|
1754
|
+
if (isGroup && !isEmptyContainer(getFromPath(formValues, fieldName))) {
|
|
1755
|
+
return;
|
|
1756
|
+
}
|
|
1699
1757
|
unsetPath(formValues, fieldName);
|
|
1700
1758
|
}
|
|
1701
1759
|
});
|
|
@@ -1802,9 +1860,12 @@
|
|
|
1802
1860
|
/**
|
|
1803
1861
|
* Sneaky function to set initial field values
|
|
1804
1862
|
*/
|
|
1805
|
-
function stageInitialValue(path, value) {
|
|
1863
|
+
function stageInitialValue(path, value, updateOriginal = false) {
|
|
1806
1864
|
setInPath(formValues, path, value);
|
|
1807
1865
|
setFieldInitialValue(path, value);
|
|
1866
|
+
if (updateOriginal) {
|
|
1867
|
+
setInPath(originalInitialValues.value, path, klona(value));
|
|
1868
|
+
}
|
|
1808
1869
|
}
|
|
1809
1870
|
async function _validateSchema() {
|
|
1810
1871
|
const schemaValue = vue.unref(schema);
|
|
@@ -1821,10 +1882,12 @@
|
|
|
1821
1882
|
}
|
|
1822
1883
|
/**
|
|
1823
1884
|
* Batches validation runs in 5ms batches
|
|
1885
|
+
* Must have two distinct batch queues to make sure they don't override each other settings #3783
|
|
1824
1886
|
*/
|
|
1825
|
-
const
|
|
1887
|
+
const debouncedSilentValidation = debounceAsync(_validateSchema, 5);
|
|
1888
|
+
const debouncedValidation = debounceAsync(_validateSchema, 5);
|
|
1826
1889
|
async function validateSchema(mode) {
|
|
1827
|
-
const formResult = await
|
|
1890
|
+
const formResult = await (mode === 'silent' ? debouncedSilentValidation() : debouncedValidation());
|
|
1828
1891
|
// fields by id lookup
|
|
1829
1892
|
const fieldsById = formCtx.fieldsByPath.value || {};
|
|
1830
1893
|
// errors fields names, we need it to also check if custom errors are updated
|
|
@@ -1914,6 +1977,7 @@
|
|
|
1914
1977
|
setValues,
|
|
1915
1978
|
setFieldTouched,
|
|
1916
1979
|
setTouched,
|
|
1980
|
+
useFieldModel,
|
|
1917
1981
|
};
|
|
1918
1982
|
}
|
|
1919
1983
|
/**
|
|
@@ -2065,16 +2129,22 @@
|
|
|
2065
2129
|
type: Function,
|
|
2066
2130
|
default: undefined,
|
|
2067
2131
|
},
|
|
2132
|
+
keepValues: {
|
|
2133
|
+
type: Boolean,
|
|
2134
|
+
default: false,
|
|
2135
|
+
},
|
|
2068
2136
|
},
|
|
2069
2137
|
setup(props, ctx) {
|
|
2070
2138
|
const initialValues = vue.toRef(props, 'initialValues');
|
|
2071
2139
|
const validationSchema = vue.toRef(props, 'validationSchema');
|
|
2140
|
+
const keepValues = vue.toRef(props, 'keepValues');
|
|
2072
2141
|
const { errors, values, meta, isSubmitting, submitCount, validate, validateField, handleReset, resetForm, handleSubmit, submitForm, setErrors, setFieldError, setFieldValue, setValues, setFieldTouched, setTouched, } = useForm({
|
|
2073
2142
|
validationSchema: validationSchema.value ? validationSchema : undefined,
|
|
2074
2143
|
initialValues,
|
|
2075
2144
|
initialErrors: props.initialErrors,
|
|
2076
2145
|
initialTouched: props.initialTouched,
|
|
2077
2146
|
validateOnMount: props.validateOnMount,
|
|
2147
|
+
keepValuesOnUnmount: keepValues,
|
|
2078
2148
|
});
|
|
2079
2149
|
const onSubmit = props.onSubmit ? handleSubmit(props.onSubmit, props.onInvalidSubmit) : submitForm;
|
|
2080
2150
|
function handleFormReset(e) {
|
|
@@ -2144,15 +2214,13 @@
|
|
|
2144
2214
|
});
|
|
2145
2215
|
const Form = FormImpl;
|
|
2146
2216
|
|
|
2147
|
-
let FIELD_ARRAY_COUNTER = 0;
|
|
2148
2217
|
function useFieldArray(arrayPath) {
|
|
2149
|
-
const id = FIELD_ARRAY_COUNTER++;
|
|
2150
2218
|
const form = injectWithSelf(FormContextKey, undefined);
|
|
2151
2219
|
const fields = vue.ref([]);
|
|
2152
2220
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
2153
2221
|
const noOp = () => { };
|
|
2154
2222
|
const noOpApi = {
|
|
2155
|
-
fields
|
|
2223
|
+
fields,
|
|
2156
2224
|
remove: noOp,
|
|
2157
2225
|
push: noOp,
|
|
2158
2226
|
swap: noOp,
|
|
@@ -2160,6 +2228,7 @@
|
|
|
2160
2228
|
update: noOp,
|
|
2161
2229
|
replace: noOp,
|
|
2162
2230
|
prepend: noOp,
|
|
2231
|
+
move: noOp,
|
|
2163
2232
|
};
|
|
2164
2233
|
if (!form) {
|
|
2165
2234
|
warn('FieldArray requires being a child of `<Form/>` or `useForm` being called before it. Array fields may not work correctly');
|
|
@@ -2169,9 +2238,13 @@
|
|
|
2169
2238
|
warn('FieldArray requires a field path to be provided, did you forget to pass the `name` prop?');
|
|
2170
2239
|
return noOpApi;
|
|
2171
2240
|
}
|
|
2241
|
+
const alreadyExists = form.fieldArrays.find(a => vue.unref(a.path) === vue.unref(arrayPath));
|
|
2242
|
+
if (alreadyExists) {
|
|
2243
|
+
return alreadyExists;
|
|
2244
|
+
}
|
|
2172
2245
|
let entryCounter = 0;
|
|
2173
2246
|
function initFields() {
|
|
2174
|
-
const currentValues = getFromPath(form === null || form === void 0 ? void 0 : form.values, vue.unref(arrayPath), []);
|
|
2247
|
+
const currentValues = getFromPath(form === null || form === void 0 ? void 0 : form.values, vue.unref(arrayPath), []) || [];
|
|
2175
2248
|
fields.value = currentValues.map(createEntry);
|
|
2176
2249
|
updateEntryFlags();
|
|
2177
2250
|
}
|
|
@@ -2188,10 +2261,20 @@
|
|
|
2188
2261
|
const key = entryCounter++;
|
|
2189
2262
|
const entry = {
|
|
2190
2263
|
key,
|
|
2191
|
-
value: vue.computed(
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2264
|
+
value: vue.computed({
|
|
2265
|
+
get() {
|
|
2266
|
+
const currentValues = getFromPath(form === null || form === void 0 ? void 0 : form.values, vue.unref(arrayPath), []) || [];
|
|
2267
|
+
const idx = fields.value.findIndex(e => e.key === key);
|
|
2268
|
+
return idx === -1 ? value : currentValues[idx];
|
|
2269
|
+
},
|
|
2270
|
+
set(value) {
|
|
2271
|
+
const idx = fields.value.findIndex(e => e.key === key);
|
|
2272
|
+
if (idx === -1) {
|
|
2273
|
+
warn(`Attempting to update a non-existent array item`);
|
|
2274
|
+
return;
|
|
2275
|
+
}
|
|
2276
|
+
update(idx, value);
|
|
2277
|
+
},
|
|
2195
2278
|
}),
|
|
2196
2279
|
isFirst: false,
|
|
2197
2280
|
isLast: false,
|
|
@@ -2284,14 +2367,26 @@
|
|
|
2284
2367
|
fields.value.unshift(createEntry(value));
|
|
2285
2368
|
updateEntryFlags();
|
|
2286
2369
|
}
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
fields
|
|
2370
|
+
function move(oldIdx, newIdx) {
|
|
2371
|
+
const pathName = vue.unref(arrayPath);
|
|
2372
|
+
const pathValue = getFromPath(form === null || form === void 0 ? void 0 : form.values, pathName);
|
|
2373
|
+
const newValue = isNullOrUndefined(pathValue) ? [] : [...pathValue];
|
|
2374
|
+
if (!Array.isArray(pathValue) || !(oldIdx in pathValue) || !(newIdx in pathValue)) {
|
|
2375
|
+
return;
|
|
2376
|
+
}
|
|
2377
|
+
const newFields = [...fields.value];
|
|
2378
|
+
const movedItem = newFields[oldIdx];
|
|
2379
|
+
newFields.splice(oldIdx, 1);
|
|
2380
|
+
newFields.splice(newIdx, 0, movedItem);
|
|
2381
|
+
const movedValue = newValue[oldIdx];
|
|
2382
|
+
newValue.splice(oldIdx, 1);
|
|
2383
|
+
newValue.splice(newIdx, 0, movedValue);
|
|
2384
|
+
form === null || form === void 0 ? void 0 : form.setFieldValue(pathName, newValue);
|
|
2385
|
+
fields.value = newFields;
|
|
2386
|
+
updateEntryFlags();
|
|
2387
|
+
}
|
|
2388
|
+
const fieldArrayCtx = {
|
|
2389
|
+
fields,
|
|
2295
2390
|
remove,
|
|
2296
2391
|
push,
|
|
2297
2392
|
swap,
|
|
@@ -2299,7 +2394,16 @@
|
|
|
2299
2394
|
update,
|
|
2300
2395
|
replace,
|
|
2301
2396
|
prepend,
|
|
2397
|
+
move,
|
|
2302
2398
|
};
|
|
2399
|
+
form.fieldArrays.push(Object.assign({ path: arrayPath, reset: initFields }, fieldArrayCtx));
|
|
2400
|
+
vue.onBeforeUnmount(() => {
|
|
2401
|
+
const idx = form.fieldArrays.findIndex(i => vue.unref(i.path) === vue.unref(arrayPath));
|
|
2402
|
+
if (idx >= 0) {
|
|
2403
|
+
form.fieldArrays.splice(idx, 1);
|
|
2404
|
+
}
|
|
2405
|
+
});
|
|
2406
|
+
return fieldArrayCtx;
|
|
2303
2407
|
}
|
|
2304
2408
|
|
|
2305
2409
|
const FieldArrayImpl = vue.defineComponent({
|
|
@@ -2312,7 +2416,7 @@
|
|
|
2312
2416
|
},
|
|
2313
2417
|
},
|
|
2314
2418
|
setup(props, ctx) {
|
|
2315
|
-
const { push, remove, swap, insert, replace, update, prepend, fields } = useFieldArray(vue.toRef(props, 'name'));
|
|
2419
|
+
const { push, remove, swap, insert, replace, update, prepend, move, fields } = useFieldArray(vue.toRef(props, 'name'));
|
|
2316
2420
|
function slotProps() {
|
|
2317
2421
|
return {
|
|
2318
2422
|
fields: fields.value,
|
|
@@ -2323,6 +2427,7 @@
|
|
|
2323
2427
|
update,
|
|
2324
2428
|
replace,
|
|
2325
2429
|
prepend,
|
|
2430
|
+
move,
|
|
2326
2431
|
};
|
|
2327
2432
|
}
|
|
2328
2433
|
ctx.expose({
|
|
@@ -2333,6 +2438,7 @@
|
|
|
2333
2438
|
update,
|
|
2334
2439
|
replace,
|
|
2335
2440
|
prepend,
|
|
2441
|
+
move,
|
|
2336
2442
|
});
|
|
2337
2443
|
return () => {
|
|
2338
2444
|
const children = normalizeChildren(undefined, ctx, slotProps);
|
|
@@ -2638,6 +2744,7 @@
|
|
|
2638
2744
|
exports.FieldContextKey = FieldContextKey;
|
|
2639
2745
|
exports.Form = Form;
|
|
2640
2746
|
exports.FormContextKey = FormContextKey;
|
|
2747
|
+
exports.IS_ABSENT = IS_ABSENT;
|
|
2641
2748
|
exports.configure = configure;
|
|
2642
2749
|
exports.defineRule = defineRule;
|
|
2643
2750
|
exports.useField = useField;
|