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.esm.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* vee-validate v4.
|
|
2
|
+
* vee-validate v4.6.0
|
|
3
3
|
* (c) 2022 Abdelrahman Awad
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
6
|
-
import { inject, getCurrentInstance, warn as warn$1, ref, unref, computed, reactive, watch, onUnmounted, nextTick, onMounted, provide, isRef, onBeforeUnmount, defineComponent, toRef, resolveDynamicComponent, h, watchEffect, markRaw
|
|
6
|
+
import { inject, getCurrentInstance, warn as warn$1, ref, unref, computed, reactive, watch, onUnmounted, nextTick, onMounted, provide, isRef, onBeforeUnmount, defineComponent, toRef, resolveDynamicComponent, h, watchEffect, markRaw } from 'vue';
|
|
7
7
|
import { setupDevtoolsPlugin } from '@vue/devtools-api';
|
|
8
8
|
|
|
9
9
|
function isCallable(fn) {
|
|
@@ -53,18 +53,6 @@ const IS_ABSENT = Symbol('Default empty value');
|
|
|
53
53
|
function isLocator(value) {
|
|
54
54
|
return isCallable(value) && !!value.__locatorRef;
|
|
55
55
|
}
|
|
56
|
-
/**
|
|
57
|
-
* Checks if an tag name is a native HTML tag and not a Vue component
|
|
58
|
-
*/
|
|
59
|
-
function isHTMLTag(tag) {
|
|
60
|
-
return ['input', 'textarea', 'select'].includes(tag);
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Checks if an input is of type file
|
|
64
|
-
*/
|
|
65
|
-
function isFileInputNode(tag, attrs) {
|
|
66
|
-
return isHTMLTag(tag) && attrs.type === 'file';
|
|
67
|
-
}
|
|
68
56
|
function isYupValidator(value) {
|
|
69
57
|
return !!value && isCallable(value.validate);
|
|
70
58
|
}
|
|
@@ -117,7 +105,7 @@ function isNativeMultiSelectNode(tag, attrs) {
|
|
|
117
105
|
* For multi-selects because the value binding will reset the value
|
|
118
106
|
*/
|
|
119
107
|
function shouldHaveValueBinding(tag, attrs) {
|
|
120
|
-
return isNativeMultiSelectNode(tag, attrs)
|
|
108
|
+
return !isNativeMultiSelectNode(tag, attrs) && attrs.type !== 'file' && !hasCheckedAttr(attrs.type);
|
|
121
109
|
}
|
|
122
110
|
function isFormSubmitEvent(evt) {
|
|
123
111
|
return isEvent(evt) && evt.target && 'submit' in evt.target;
|
|
@@ -301,6 +289,15 @@ function debounceAsync(inner, ms = 0) {
|
|
|
301
289
|
}, ms);
|
|
302
290
|
return new Promise(resolve => resolves.push(resolve));
|
|
303
291
|
};
|
|
292
|
+
}
|
|
293
|
+
function applyModelModifiers(value, modifiers) {
|
|
294
|
+
if (!isObject(modifiers)) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
if (modifiers.number) {
|
|
298
|
+
return toNumber(value);
|
|
299
|
+
}
|
|
300
|
+
return value;
|
|
304
301
|
}
|
|
305
302
|
|
|
306
303
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -344,7 +341,8 @@ function normalizeEventValue(value) {
|
|
|
344
341
|
return getBoundValue(input);
|
|
345
342
|
}
|
|
346
343
|
if (input.type === 'file' && input.files) {
|
|
347
|
-
|
|
344
|
+
const files = Array.from(input.files);
|
|
345
|
+
return input.multiple ? files : files[0];
|
|
348
346
|
}
|
|
349
347
|
if (isNativeMultiSelect(input)) {
|
|
350
348
|
return Array.from(input.options)
|
|
@@ -843,8 +841,8 @@ function useFieldState(path, init) {
|
|
|
843
841
|
/**
|
|
844
842
|
* Creates the field value and resolves the initial value
|
|
845
843
|
*/
|
|
846
|
-
function _useFieldValue(path, modelValue, shouldInjectForm) {
|
|
847
|
-
const form = shouldInjectForm ? injectWithSelf(FormContextKey, undefined) : undefined;
|
|
844
|
+
function _useFieldValue(path, modelValue, shouldInjectForm = true) {
|
|
845
|
+
const form = shouldInjectForm === true ? injectWithSelf(FormContextKey, undefined) : undefined;
|
|
848
846
|
const modelRef = ref(unref(modelValue));
|
|
849
847
|
function resolveInitialValue() {
|
|
850
848
|
if (!form) {
|
|
@@ -874,7 +872,7 @@ function _useFieldValue(path, modelValue, shouldInjectForm) {
|
|
|
874
872
|
// prioritize model value over form values
|
|
875
873
|
// #3429
|
|
876
874
|
const currentValue = modelValue ? unref(modelValue) : getFromPath(form.values, unref(path), unref(initialValue));
|
|
877
|
-
form.stageInitialValue(unref(path), currentValue);
|
|
875
|
+
form.stageInitialValue(unref(path), currentValue, true);
|
|
878
876
|
// otherwise use a computed setter that triggers the `setFieldValue`
|
|
879
877
|
const value = computed({
|
|
880
878
|
get() {
|
|
@@ -1313,7 +1311,7 @@ function useField(name, rules, opts) {
|
|
|
1313
1311
|
return _useField(name, rules, opts);
|
|
1314
1312
|
}
|
|
1315
1313
|
function _useField(name, rules, opts) {
|
|
1316
|
-
const { initialValue: modelValue, validateOnMount, bails, type, checkedValue, label, validateOnValueUpdate, uncheckedValue, standalone, } = normalizeOptions(unref(name), opts);
|
|
1314
|
+
const { initialValue: modelValue, validateOnMount, bails, type, checkedValue, label, validateOnValueUpdate, uncheckedValue, standalone, keepValueOnUnmount, modelPropName, syncVModel, } = normalizeOptions(unref(name), opts);
|
|
1317
1315
|
const form = !standalone ? injectWithSelf(FormContextKey) : undefined;
|
|
1318
1316
|
// a flag indicating if the field is about to be removed/unmounted.
|
|
1319
1317
|
let markedForRemoval = false;
|
|
@@ -1321,6 +1319,9 @@ function _useField(name, rules, opts) {
|
|
|
1321
1319
|
modelValue,
|
|
1322
1320
|
standalone,
|
|
1323
1321
|
});
|
|
1322
|
+
if (syncVModel) {
|
|
1323
|
+
useVModel({ value, prop: modelPropName, handleChange });
|
|
1324
|
+
}
|
|
1324
1325
|
/**
|
|
1325
1326
|
* Handles common onBlur meta update
|
|
1326
1327
|
*/
|
|
@@ -1379,13 +1380,13 @@ function _useField(name, rules, opts) {
|
|
|
1379
1380
|
return validateValidStateOnly();
|
|
1380
1381
|
}
|
|
1381
1382
|
// Common input/change event handler
|
|
1382
|
-
|
|
1383
|
+
function handleChange(e, shouldValidate = true) {
|
|
1383
1384
|
const newValue = normalizeEventValue(e);
|
|
1384
1385
|
value.value = newValue;
|
|
1385
1386
|
if (!validateOnValueUpdate && shouldValidate) {
|
|
1386
1387
|
validateWithStateMutation();
|
|
1387
1388
|
}
|
|
1388
|
-
}
|
|
1389
|
+
}
|
|
1389
1390
|
// Runs the initial validation
|
|
1390
1391
|
onMounted(() => {
|
|
1391
1392
|
if (validateOnMount) {
|
|
@@ -1402,7 +1403,13 @@ function _useField(name, rules, opts) {
|
|
|
1402
1403
|
}
|
|
1403
1404
|
let unwatchValue;
|
|
1404
1405
|
function watchValue() {
|
|
1405
|
-
unwatchValue = watch(value,
|
|
1406
|
+
unwatchValue = watch(value, (val, oldVal) => {
|
|
1407
|
+
if (es6(val, oldVal)) {
|
|
1408
|
+
return;
|
|
1409
|
+
}
|
|
1410
|
+
const validateFn = validateOnValueUpdate ? validateWithStateMutation : validateValidStateOnly;
|
|
1411
|
+
validateFn();
|
|
1412
|
+
}, {
|
|
1406
1413
|
deep: true,
|
|
1407
1414
|
});
|
|
1408
1415
|
}
|
|
@@ -1443,6 +1450,7 @@ function _useField(name, rules, opts) {
|
|
|
1443
1450
|
checkedValue,
|
|
1444
1451
|
uncheckedValue,
|
|
1445
1452
|
bails,
|
|
1453
|
+
keepValueOnUnmount,
|
|
1446
1454
|
resetField,
|
|
1447
1455
|
handleReset: () => resetField(),
|
|
1448
1456
|
validate: validate$1,
|
|
@@ -1529,6 +1537,9 @@ function normalizeOptions(name, opts) {
|
|
|
1529
1537
|
label: name,
|
|
1530
1538
|
validateOnValueUpdate: true,
|
|
1531
1539
|
standalone: false,
|
|
1540
|
+
keepValueOnUnmount: undefined,
|
|
1541
|
+
modelPropName: 'modelValue',
|
|
1542
|
+
syncVModel: true,
|
|
1532
1543
|
});
|
|
1533
1544
|
if (!opts) {
|
|
1534
1545
|
return defaults();
|
|
@@ -1560,8 +1571,8 @@ function useCheckboxField(name, rules, opts) {
|
|
|
1560
1571
|
return Array.isArray(currentValue) ? currentValue.includes(checkedVal) : checkedVal === currentValue;
|
|
1561
1572
|
});
|
|
1562
1573
|
function handleCheckboxChange(e, shouldValidate = true) {
|
|
1563
|
-
var _a
|
|
1564
|
-
if (checked.value === ((
|
|
1574
|
+
var _a;
|
|
1575
|
+
if (checked.value === ((_a = e === null || e === void 0 ? void 0 : e.target) === null || _a === void 0 ? void 0 : _a.checked)) {
|
|
1565
1576
|
return;
|
|
1566
1577
|
}
|
|
1567
1578
|
let newValue = normalizeEventValue(e);
|
|
@@ -1572,8 +1583,10 @@ function useCheckboxField(name, rules, opts) {
|
|
|
1572
1583
|
handleChange(newValue, shouldValidate);
|
|
1573
1584
|
}
|
|
1574
1585
|
onBeforeUnmount(() => {
|
|
1575
|
-
|
|
1576
|
-
|
|
1586
|
+
var _a, _b;
|
|
1587
|
+
const shouldKeepValue = (_b = (_a = unref(field.keepValueOnUnmount)) !== null && _a !== void 0 ? _a : unref(form === null || form === void 0 ? void 0 : form.keepValuesOnUnmount)) !== null && _b !== void 0 ? _b : false;
|
|
1588
|
+
// toggles the checkbox value if it was checked and the unset behavior is set
|
|
1589
|
+
if (checked.value && !shouldKeepValue) {
|
|
1577
1590
|
handleCheckboxChange(unref(checkedValue), false);
|
|
1578
1591
|
}
|
|
1579
1592
|
});
|
|
@@ -1582,6 +1595,41 @@ function useCheckboxField(name, rules, opts) {
|
|
|
1582
1595
|
uncheckedValue, handleChange: handleCheckboxChange });
|
|
1583
1596
|
}
|
|
1584
1597
|
return patchCheckboxApi(_useField(name, rules, opts));
|
|
1598
|
+
}
|
|
1599
|
+
function useVModel({ prop, value, handleChange }) {
|
|
1600
|
+
const vm = getCurrentInstance();
|
|
1601
|
+
/* istanbul ignore next */
|
|
1602
|
+
if (!vm) {
|
|
1603
|
+
if ((process.env.NODE_ENV !== 'production')) {
|
|
1604
|
+
console.warn('Failed to setup model events because `useField` was not called in setup.');
|
|
1605
|
+
}
|
|
1606
|
+
return;
|
|
1607
|
+
}
|
|
1608
|
+
const propName = prop || 'modelValue';
|
|
1609
|
+
const emitName = `update:${propName}`;
|
|
1610
|
+
// Component doesn't have a model prop setup (must be defined on the props)
|
|
1611
|
+
if (!(propName in vm.props)) {
|
|
1612
|
+
return;
|
|
1613
|
+
}
|
|
1614
|
+
watch(value, newValue => {
|
|
1615
|
+
if (es6(newValue, getCurrentModelValue(vm, propName))) {
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1618
|
+
vm.emit(emitName, newValue);
|
|
1619
|
+
});
|
|
1620
|
+
watch(() => getCurrentModelValue(vm, propName), propValue => {
|
|
1621
|
+
if (propValue === IS_ABSENT && value.value === undefined) {
|
|
1622
|
+
return;
|
|
1623
|
+
}
|
|
1624
|
+
const newValue = propValue === IS_ABSENT ? undefined : propValue;
|
|
1625
|
+
if (es6(newValue, applyModelModifiers(value.value, vm.props.modelModifiers))) {
|
|
1626
|
+
return;
|
|
1627
|
+
}
|
|
1628
|
+
handleChange(newValue);
|
|
1629
|
+
});
|
|
1630
|
+
}
|
|
1631
|
+
function getCurrentModelValue(vm, propName) {
|
|
1632
|
+
return vm.props[propName];
|
|
1585
1633
|
}
|
|
1586
1634
|
|
|
1587
1635
|
const FieldImpl = defineComponent({
|
|
@@ -1648,13 +1696,17 @@ const FieldImpl = defineComponent({
|
|
|
1648
1696
|
type: Boolean,
|
|
1649
1697
|
default: false,
|
|
1650
1698
|
},
|
|
1699
|
+
keepValue: {
|
|
1700
|
+
type: Boolean,
|
|
1701
|
+
default: undefined,
|
|
1702
|
+
},
|
|
1651
1703
|
},
|
|
1652
1704
|
setup(props, ctx) {
|
|
1653
1705
|
const rules = toRef(props, 'rules');
|
|
1654
1706
|
const name = toRef(props, 'name');
|
|
1655
1707
|
const label = toRef(props, 'label');
|
|
1656
1708
|
const uncheckedValue = toRef(props, 'uncheckedValue');
|
|
1657
|
-
const
|
|
1709
|
+
const keepValue = toRef(props, 'keepValue');
|
|
1658
1710
|
const { errors, value, errorMessage, validate: validateField, handleChange, handleBlur, setTouched, resetField, handleReset, meta, checked, setErrors, } = useField(name, rules, {
|
|
1659
1711
|
validateOnMount: props.validateOnMount,
|
|
1660
1712
|
bails: props.bails,
|
|
@@ -1666,25 +1718,22 @@ const FieldImpl = defineComponent({
|
|
|
1666
1718
|
uncheckedValue,
|
|
1667
1719
|
label,
|
|
1668
1720
|
validateOnValueUpdate: false,
|
|
1721
|
+
keepValueOnUnmount: keepValue,
|
|
1669
1722
|
});
|
|
1670
1723
|
// If there is a v-model applied on the component we need to emit the `update:modelValue` whenever the value binding changes
|
|
1671
|
-
const onChangeHandler =
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
}
|
|
1676
|
-
: handleChange;
|
|
1724
|
+
const onChangeHandler = function handleChangeWithModel(e, shouldValidate = true) {
|
|
1725
|
+
handleChange(e, shouldValidate);
|
|
1726
|
+
ctx.emit('update:modelValue', value.value);
|
|
1727
|
+
};
|
|
1677
1728
|
const handleInput = (e) => {
|
|
1678
1729
|
if (!hasCheckedAttr(ctx.attrs.type)) {
|
|
1679
1730
|
value.value = normalizeEventValue(e);
|
|
1680
1731
|
}
|
|
1681
1732
|
};
|
|
1682
|
-
const onInputHandler =
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
}
|
|
1687
|
-
: handleInput;
|
|
1733
|
+
const onInputHandler = function handleInputWithModel(e) {
|
|
1734
|
+
handleInput(e);
|
|
1735
|
+
ctx.emit('update:modelValue', value.value);
|
|
1736
|
+
};
|
|
1688
1737
|
const fieldProps = computed(() => {
|
|
1689
1738
|
const { validateOnInput, validateOnChange, validateOnBlur, validateOnModelUpdate } = resolveValidationTriggers(props);
|
|
1690
1739
|
const baseOnBlur = [handleBlur, ctx.attrs.onBlur, validateOnBlur ? validateField : undefined].filter(Boolean);
|
|
@@ -1700,26 +1749,12 @@ const FieldImpl = defineComponent({
|
|
|
1700
1749
|
if (hasCheckedAttr(ctx.attrs.type) && checked) {
|
|
1701
1750
|
attrs.checked = checked.value;
|
|
1702
1751
|
}
|
|
1703
|
-
else {
|
|
1704
|
-
attrs.value = value.value;
|
|
1705
|
-
}
|
|
1706
1752
|
const tag = resolveTag(props, ctx);
|
|
1707
1753
|
if (shouldHaveValueBinding(tag, ctx.attrs)) {
|
|
1708
|
-
|
|
1754
|
+
attrs.value = value.value;
|
|
1709
1755
|
}
|
|
1710
1756
|
return attrs;
|
|
1711
1757
|
});
|
|
1712
|
-
const modelValue = toRef(props, 'modelValue');
|
|
1713
|
-
watch(modelValue, newModelValue => {
|
|
1714
|
-
// Don't attempt to sync absent values
|
|
1715
|
-
if (newModelValue === IS_ABSENT && value.value === undefined) {
|
|
1716
|
-
return;
|
|
1717
|
-
}
|
|
1718
|
-
if (newModelValue !== applyModifiers(value.value, props.modelModifiers)) {
|
|
1719
|
-
value.value = newModelValue === IS_ABSENT ? undefined : newModelValue;
|
|
1720
|
-
validateField();
|
|
1721
|
-
}
|
|
1722
|
-
});
|
|
1723
1758
|
function slotProps() {
|
|
1724
1759
|
return {
|
|
1725
1760
|
field: fieldProps.value,
|
|
@@ -1771,12 +1806,6 @@ function resolveValidationTriggers(props) {
|
|
|
1771
1806
|
validateOnModelUpdate: (_d = props.validateOnModelUpdate) !== null && _d !== void 0 ? _d : validateOnModelUpdate,
|
|
1772
1807
|
};
|
|
1773
1808
|
}
|
|
1774
|
-
function applyModifiers(value, modifiers) {
|
|
1775
|
-
if (modifiers.number) {
|
|
1776
|
-
return toNumber(value);
|
|
1777
|
-
}
|
|
1778
|
-
return value;
|
|
1779
|
-
}
|
|
1780
1809
|
function resolveInitialValue(props, ctx) {
|
|
1781
1810
|
// Gets the initial value either from `value` prop/attr or `v-model` binding (modelValue)
|
|
1782
1811
|
// For checkboxes and radio buttons it will always be the model value not the `value` attribute
|
|
@@ -1789,6 +1818,7 @@ const Field = FieldImpl;
|
|
|
1789
1818
|
|
|
1790
1819
|
let FORM_COUNTER = 0;
|
|
1791
1820
|
function useForm(opts) {
|
|
1821
|
+
var _a;
|
|
1792
1822
|
const formId = FORM_COUNTER++;
|
|
1793
1823
|
// Prevents fields from double resetting their values, which causes checkboxes to toggle their initial value
|
|
1794
1824
|
// TODO: This won't be needed if we centralize all the state inside the `form` for form inputs
|
|
@@ -1799,8 +1829,8 @@ function useForm(opts) {
|
|
|
1799
1829
|
const isSubmitting = ref(false);
|
|
1800
1830
|
// The number of times the user tried to submit the form
|
|
1801
1831
|
const submitCount = ref(0);
|
|
1802
|
-
//
|
|
1803
|
-
const
|
|
1832
|
+
// field arrays managed by this form
|
|
1833
|
+
const fieldArrays = [];
|
|
1804
1834
|
// a private ref for all form values
|
|
1805
1835
|
const formValues = reactive(klona(unref(opts === null || opts === void 0 ? void 0 : opts.initialValues) || {}));
|
|
1806
1836
|
// the source of errors for the form fields
|
|
@@ -1847,10 +1877,11 @@ function useForm(opts) {
|
|
|
1847
1877
|
// mutable non-reactive reference to initial errors
|
|
1848
1878
|
// we need this to process initial errors then unset them
|
|
1849
1879
|
const initialErrors = Object.assign({}, ((opts === null || opts === void 0 ? void 0 : opts.initialErrors) || {}));
|
|
1880
|
+
const keepValuesOnUnmount = (_a = opts === null || opts === void 0 ? void 0 : opts.keepValuesOnUnmount) !== null && _a !== void 0 ? _a : false;
|
|
1850
1881
|
// initial form values
|
|
1851
1882
|
const { initialValues, originalInitialValues, setInitialValues } = useFormInitialValues(fieldsByPath, formValues, opts === null || opts === void 0 ? void 0 : opts.initialValues);
|
|
1852
1883
|
// form meta aggregations
|
|
1853
|
-
const meta = useFormMeta(fieldsByPath, formValues,
|
|
1884
|
+
const meta = useFormMeta(fieldsByPath, formValues, originalInitialValues, errors);
|
|
1854
1885
|
const schema = opts === null || opts === void 0 ? void 0 : opts.validationSchema;
|
|
1855
1886
|
const formCtx = {
|
|
1856
1887
|
formId,
|
|
@@ -1862,7 +1893,8 @@ function useForm(opts) {
|
|
|
1862
1893
|
submitCount,
|
|
1863
1894
|
meta,
|
|
1864
1895
|
isSubmitting,
|
|
1865
|
-
|
|
1896
|
+
fieldArrays,
|
|
1897
|
+
keepValuesOnUnmount,
|
|
1866
1898
|
validateSchema: unref(schema) ? validateSchema : undefined,
|
|
1867
1899
|
validate,
|
|
1868
1900
|
register: registerField,
|
|
@@ -1880,6 +1912,7 @@ function useForm(opts) {
|
|
|
1880
1912
|
stageInitialValue,
|
|
1881
1913
|
unsetInitialValue,
|
|
1882
1914
|
setFieldInitialValue,
|
|
1915
|
+
useFieldModel,
|
|
1883
1916
|
};
|
|
1884
1917
|
function isFieldGroup(fieldOrGroup) {
|
|
1885
1918
|
return Array.isArray(fieldOrGroup);
|
|
@@ -1949,7 +1982,22 @@ function useForm(opts) {
|
|
|
1949
1982
|
setFieldValue(path, fields[path]);
|
|
1950
1983
|
});
|
|
1951
1984
|
// regenerate the arrays when the form values change
|
|
1952
|
-
|
|
1985
|
+
fieldArrays.forEach(f => f && f.reset());
|
|
1986
|
+
}
|
|
1987
|
+
function createModel(path) {
|
|
1988
|
+
const { value } = _useFieldValue(path);
|
|
1989
|
+
watch(value, () => {
|
|
1990
|
+
if (!fieldExists(unref(path))) {
|
|
1991
|
+
validate({ mode: 'validated-only' });
|
|
1992
|
+
}
|
|
1993
|
+
});
|
|
1994
|
+
return value;
|
|
1995
|
+
}
|
|
1996
|
+
function useFieldModel(path) {
|
|
1997
|
+
if (!Array.isArray(path)) {
|
|
1998
|
+
return createModel(path);
|
|
1999
|
+
}
|
|
2000
|
+
return path.map(createModel);
|
|
1953
2001
|
}
|
|
1954
2002
|
/**
|
|
1955
2003
|
* Sets the touched meta state on a field
|
|
@@ -2073,13 +2121,26 @@ function useForm(opts) {
|
|
|
2073
2121
|
}
|
|
2074
2122
|
function unregisterField(field) {
|
|
2075
2123
|
const fieldName = unref(field.name);
|
|
2124
|
+
const fieldInstance = fieldsByPath.value[fieldName];
|
|
2125
|
+
const isGroup = !!fieldInstance && isFieldGroup(fieldInstance);
|
|
2076
2126
|
removeFieldFromPath(field, fieldName);
|
|
2077
2127
|
nextTick(() => {
|
|
2128
|
+
var _a;
|
|
2078
2129
|
// clears a field error on unmounted
|
|
2079
2130
|
// we wait till next tick to make sure if the field is completely removed and doesn't have any siblings like checkboxes
|
|
2080
2131
|
// #3384
|
|
2081
2132
|
if (!fieldExists(fieldName)) {
|
|
2082
2133
|
setFieldError(fieldName, undefined);
|
|
2134
|
+
// Checks if the field was configured to be unset during unmount or not
|
|
2135
|
+
// Checks both the form-level config and field-level one
|
|
2136
|
+
// Field has the priority if it is set, otherwise it goes to the form settings
|
|
2137
|
+
const shouldKeepValue = (_a = unref(field.keepValueOnUnmount)) !== null && _a !== void 0 ? _a : unref(keepValuesOnUnmount);
|
|
2138
|
+
if (shouldKeepValue) {
|
|
2139
|
+
return;
|
|
2140
|
+
}
|
|
2141
|
+
if (isGroup && !isEmptyContainer(getFromPath(formValues, fieldName))) {
|
|
2142
|
+
return;
|
|
2143
|
+
}
|
|
2083
2144
|
unsetPath(formValues, fieldName);
|
|
2084
2145
|
}
|
|
2085
2146
|
});
|
|
@@ -2186,9 +2247,12 @@ function useForm(opts) {
|
|
|
2186
2247
|
/**
|
|
2187
2248
|
* Sneaky function to set initial field values
|
|
2188
2249
|
*/
|
|
2189
|
-
function stageInitialValue(path, value) {
|
|
2250
|
+
function stageInitialValue(path, value, updateOriginal = false) {
|
|
2190
2251
|
setInPath(formValues, path, value);
|
|
2191
2252
|
setFieldInitialValue(path, value);
|
|
2253
|
+
if (updateOriginal) {
|
|
2254
|
+
setInPath(originalInitialValues.value, path, klona(value));
|
|
2255
|
+
}
|
|
2192
2256
|
}
|
|
2193
2257
|
async function _validateSchema() {
|
|
2194
2258
|
const schemaValue = unref(schema);
|
|
@@ -2205,10 +2269,12 @@ function useForm(opts) {
|
|
|
2205
2269
|
}
|
|
2206
2270
|
/**
|
|
2207
2271
|
* Batches validation runs in 5ms batches
|
|
2272
|
+
* Must have two distinct batch queues to make sure they don't override each other settings #3783
|
|
2208
2273
|
*/
|
|
2209
|
-
const
|
|
2274
|
+
const debouncedSilentValidation = debounceAsync(_validateSchema, 5);
|
|
2275
|
+
const debouncedValidation = debounceAsync(_validateSchema, 5);
|
|
2210
2276
|
async function validateSchema(mode) {
|
|
2211
|
-
const formResult = await
|
|
2277
|
+
const formResult = await (mode === 'silent' ? debouncedSilentValidation() : debouncedValidation());
|
|
2212
2278
|
// fields by id lookup
|
|
2213
2279
|
const fieldsById = formCtx.fieldsByPath.value || {};
|
|
2214
2280
|
// errors fields names, we need it to also check if custom errors are updated
|
|
@@ -2304,6 +2370,7 @@ function useForm(opts) {
|
|
|
2304
2370
|
setValues,
|
|
2305
2371
|
setFieldTouched,
|
|
2306
2372
|
setTouched,
|
|
2373
|
+
useFieldModel,
|
|
2307
2374
|
};
|
|
2308
2375
|
}
|
|
2309
2376
|
/**
|
|
@@ -2455,16 +2522,22 @@ const FormImpl = defineComponent({
|
|
|
2455
2522
|
type: Function,
|
|
2456
2523
|
default: undefined,
|
|
2457
2524
|
},
|
|
2525
|
+
keepValues: {
|
|
2526
|
+
type: Boolean,
|
|
2527
|
+
default: false,
|
|
2528
|
+
},
|
|
2458
2529
|
},
|
|
2459
2530
|
setup(props, ctx) {
|
|
2460
2531
|
const initialValues = toRef(props, 'initialValues');
|
|
2461
2532
|
const validationSchema = toRef(props, 'validationSchema');
|
|
2533
|
+
const keepValues = toRef(props, 'keepValues');
|
|
2462
2534
|
const { errors, values, meta, isSubmitting, submitCount, validate, validateField, handleReset, resetForm, handleSubmit, submitForm, setErrors, setFieldError, setFieldValue, setValues, setFieldTouched, setTouched, } = useForm({
|
|
2463
2535
|
validationSchema: validationSchema.value ? validationSchema : undefined,
|
|
2464
2536
|
initialValues,
|
|
2465
2537
|
initialErrors: props.initialErrors,
|
|
2466
2538
|
initialTouched: props.initialTouched,
|
|
2467
2539
|
validateOnMount: props.validateOnMount,
|
|
2540
|
+
keepValuesOnUnmount: keepValues,
|
|
2468
2541
|
});
|
|
2469
2542
|
const onSubmit = props.onSubmit ? handleSubmit(props.onSubmit, props.onInvalidSubmit) : submitForm;
|
|
2470
2543
|
function handleFormReset(e) {
|
|
@@ -2534,15 +2607,13 @@ const FormImpl = defineComponent({
|
|
|
2534
2607
|
});
|
|
2535
2608
|
const Form = FormImpl;
|
|
2536
2609
|
|
|
2537
|
-
let FIELD_ARRAY_COUNTER = 0;
|
|
2538
2610
|
function useFieldArray(arrayPath) {
|
|
2539
|
-
const id = FIELD_ARRAY_COUNTER++;
|
|
2540
2611
|
const form = injectWithSelf(FormContextKey, undefined);
|
|
2541
2612
|
const fields = ref([]);
|
|
2542
2613
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
2543
2614
|
const noOp = () => { };
|
|
2544
2615
|
const noOpApi = {
|
|
2545
|
-
fields
|
|
2616
|
+
fields,
|
|
2546
2617
|
remove: noOp,
|
|
2547
2618
|
push: noOp,
|
|
2548
2619
|
swap: noOp,
|
|
@@ -2550,6 +2621,7 @@ function useFieldArray(arrayPath) {
|
|
|
2550
2621
|
update: noOp,
|
|
2551
2622
|
replace: noOp,
|
|
2552
2623
|
prepend: noOp,
|
|
2624
|
+
move: noOp,
|
|
2553
2625
|
};
|
|
2554
2626
|
if (!form) {
|
|
2555
2627
|
warn('FieldArray requires being a child of `<Form/>` or `useForm` being called before it. Array fields may not work correctly');
|
|
@@ -2559,9 +2631,13 @@ function useFieldArray(arrayPath) {
|
|
|
2559
2631
|
warn('FieldArray requires a field path to be provided, did you forget to pass the `name` prop?');
|
|
2560
2632
|
return noOpApi;
|
|
2561
2633
|
}
|
|
2634
|
+
const alreadyExists = form.fieldArrays.find(a => unref(a.path) === unref(arrayPath));
|
|
2635
|
+
if (alreadyExists) {
|
|
2636
|
+
return alreadyExists;
|
|
2637
|
+
}
|
|
2562
2638
|
let entryCounter = 0;
|
|
2563
2639
|
function initFields() {
|
|
2564
|
-
const currentValues = getFromPath(form === null || form === void 0 ? void 0 : form.values, unref(arrayPath), []);
|
|
2640
|
+
const currentValues = getFromPath(form === null || form === void 0 ? void 0 : form.values, unref(arrayPath), []) || [];
|
|
2565
2641
|
fields.value = currentValues.map(createEntry);
|
|
2566
2642
|
updateEntryFlags();
|
|
2567
2643
|
}
|
|
@@ -2578,10 +2654,20 @@ function useFieldArray(arrayPath) {
|
|
|
2578
2654
|
const key = entryCounter++;
|
|
2579
2655
|
const entry = {
|
|
2580
2656
|
key,
|
|
2581
|
-
value: computed(
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2657
|
+
value: computed({
|
|
2658
|
+
get() {
|
|
2659
|
+
const currentValues = getFromPath(form === null || form === void 0 ? void 0 : form.values, unref(arrayPath), []) || [];
|
|
2660
|
+
const idx = fields.value.findIndex(e => e.key === key);
|
|
2661
|
+
return idx === -1 ? value : currentValues[idx];
|
|
2662
|
+
},
|
|
2663
|
+
set(value) {
|
|
2664
|
+
const idx = fields.value.findIndex(e => e.key === key);
|
|
2665
|
+
if (idx === -1) {
|
|
2666
|
+
warn(`Attempting to update a non-existent array item`);
|
|
2667
|
+
return;
|
|
2668
|
+
}
|
|
2669
|
+
update(idx, value);
|
|
2670
|
+
},
|
|
2585
2671
|
}),
|
|
2586
2672
|
isFirst: false,
|
|
2587
2673
|
isLast: false,
|
|
@@ -2674,14 +2760,26 @@ function useFieldArray(arrayPath) {
|
|
|
2674
2760
|
fields.value.unshift(createEntry(value));
|
|
2675
2761
|
updateEntryFlags();
|
|
2676
2762
|
}
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2763
|
+
function move(oldIdx, newIdx) {
|
|
2764
|
+
const pathName = unref(arrayPath);
|
|
2765
|
+
const pathValue = getFromPath(form === null || form === void 0 ? void 0 : form.values, pathName);
|
|
2766
|
+
const newValue = isNullOrUndefined(pathValue) ? [] : [...pathValue];
|
|
2767
|
+
if (!Array.isArray(pathValue) || !(oldIdx in pathValue) || !(newIdx in pathValue)) {
|
|
2768
|
+
return;
|
|
2769
|
+
}
|
|
2770
|
+
const newFields = [...fields.value];
|
|
2771
|
+
const movedItem = newFields[oldIdx];
|
|
2772
|
+
newFields.splice(oldIdx, 1);
|
|
2773
|
+
newFields.splice(newIdx, 0, movedItem);
|
|
2774
|
+
const movedValue = newValue[oldIdx];
|
|
2775
|
+
newValue.splice(oldIdx, 1);
|
|
2776
|
+
newValue.splice(newIdx, 0, movedValue);
|
|
2777
|
+
form === null || form === void 0 ? void 0 : form.setFieldValue(pathName, newValue);
|
|
2778
|
+
fields.value = newFields;
|
|
2779
|
+
updateEntryFlags();
|
|
2780
|
+
}
|
|
2781
|
+
const fieldArrayCtx = {
|
|
2782
|
+
fields,
|
|
2685
2783
|
remove,
|
|
2686
2784
|
push,
|
|
2687
2785
|
swap,
|
|
@@ -2689,7 +2787,16 @@ function useFieldArray(arrayPath) {
|
|
|
2689
2787
|
update,
|
|
2690
2788
|
replace,
|
|
2691
2789
|
prepend,
|
|
2790
|
+
move,
|
|
2692
2791
|
};
|
|
2792
|
+
form.fieldArrays.push(Object.assign({ path: arrayPath, reset: initFields }, fieldArrayCtx));
|
|
2793
|
+
onBeforeUnmount(() => {
|
|
2794
|
+
const idx = form.fieldArrays.findIndex(i => unref(i.path) === unref(arrayPath));
|
|
2795
|
+
if (idx >= 0) {
|
|
2796
|
+
form.fieldArrays.splice(idx, 1);
|
|
2797
|
+
}
|
|
2798
|
+
});
|
|
2799
|
+
return fieldArrayCtx;
|
|
2693
2800
|
}
|
|
2694
2801
|
|
|
2695
2802
|
const FieldArrayImpl = defineComponent({
|
|
@@ -2702,7 +2809,7 @@ const FieldArrayImpl = defineComponent({
|
|
|
2702
2809
|
},
|
|
2703
2810
|
},
|
|
2704
2811
|
setup(props, ctx) {
|
|
2705
|
-
const { push, remove, swap, insert, replace, update, prepend, fields } = useFieldArray(toRef(props, 'name'));
|
|
2812
|
+
const { push, remove, swap, insert, replace, update, prepend, move, fields } = useFieldArray(toRef(props, 'name'));
|
|
2706
2813
|
function slotProps() {
|
|
2707
2814
|
return {
|
|
2708
2815
|
fields: fields.value,
|
|
@@ -2713,6 +2820,7 @@ const FieldArrayImpl = defineComponent({
|
|
|
2713
2820
|
update,
|
|
2714
2821
|
replace,
|
|
2715
2822
|
prepend,
|
|
2823
|
+
move,
|
|
2716
2824
|
};
|
|
2717
2825
|
}
|
|
2718
2826
|
ctx.expose({
|
|
@@ -2723,6 +2831,7 @@ const FieldArrayImpl = defineComponent({
|
|
|
2723
2831
|
update,
|
|
2724
2832
|
replace,
|
|
2725
2833
|
prepend,
|
|
2834
|
+
move,
|
|
2726
2835
|
});
|
|
2727
2836
|
return () => {
|
|
2728
2837
|
const children = normalizeChildren(undefined, ctx, slotProps);
|
|
@@ -3022,4 +3131,4 @@ function useSubmitForm(cb) {
|
|
|
3022
3131
|
};
|
|
3023
3132
|
}
|
|
3024
3133
|
|
|
3025
|
-
export { ErrorMessage, Field, FieldArray, FieldContextKey, Form, FormContextKey, configure, defineRule, useField, useFieldArray, useFieldError, useFieldValue, useForm, useFormErrors, useFormValues, useIsFieldDirty, useIsFieldTouched, useIsFieldValid, useIsFormDirty, useIsFormTouched, useIsFormValid, useIsSubmitting, useResetForm, useSubmitCount, useSubmitForm, useValidateField, useValidateForm, validate };
|
|
3134
|
+
export { ErrorMessage, Field, FieldArray, FieldContextKey, Form, FormContextKey, IS_ABSENT, configure, defineRule, useField, useFieldArray, useFieldError, useFieldValue, useForm, useFormErrors, useFormValues, useIsFieldDirty, useIsFieldTouched, useIsFieldValid, useIsFormDirty, useIsFormTouched, useIsFormValid, useIsSubmitting, useResetForm, useSubmitCount, useSubmitForm, useValidateField, useValidateForm, validate };
|