/
Form.ts
154 lines (142 loc) · 4.03 KB
/
Form.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import { h, defineComponent, toRef, resolveDynamicComponent, computed, PropType } from 'vue';
import { useForm } from './useForm';
import { SubmissionHandler, SubmitEvent } from './types';
import { isEvent, normalizeChildren } from './utils';
export const Form = defineComponent({
name: 'Form',
inheritAttrs: false,
props: {
as: {
type: String,
default: 'form',
},
validationSchema: {
type: Object,
default: undefined,
},
initialValues: {
type: Object,
default: undefined,
},
initialErrors: {
type: Object,
default: undefined,
},
initialTouched: {
type: Object,
default: undefined,
},
validateOnMount: {
type: Boolean,
default: false,
},
onSubmit: {
type: Function as PropType<SubmissionHandler>,
default: undefined,
},
},
setup(props, ctx) {
const initialValues = toRef(props, 'initialValues');
const validationSchema = toRef(props, 'validationSchema');
const {
errors,
values,
meta,
isSubmitting,
submitCount,
validate,
validateField,
handleReset,
resetForm,
handleSubmit,
submitForm,
setErrors,
setFieldError,
setFieldValue,
setValues,
setFieldTouched,
setTouched,
} = useForm({
validationSchema: validationSchema.value ? validationSchema : undefined,
initialValues,
initialErrors: props.initialErrors,
initialTouched: props.initialTouched,
validateOnMount: props.validateOnMount,
});
const onSubmit = props.onSubmit ? handleSubmit(props.onSubmit) : submitForm;
function handleFormReset(e?: Event) {
if (isEvent(e)) {
// Prevent default form reset behavior
e.preventDefault();
}
handleReset();
if (typeof ctx.attrs.onReset === 'function') {
ctx.attrs.onReset();
}
}
function handleScopedSlotSubmit(evt: Event | SubmissionHandler, onSubmit?: SubmissionHandler) {
const onSuccess = typeof evt === 'function' && !onSubmit ? evt : onSubmit;
return handleSubmit(onSuccess as SubmissionHandler<Record<string, unknown>>)(evt as SubmitEvent);
}
const slotProps = computed(() => {
return {
meta: meta.value,
errors: errors.value,
values: values,
isSubmitting: isSubmitting.value,
submitCount: submitCount.value,
validate,
validateField,
handleSubmit: handleScopedSlotSubmit,
handleReset,
submitForm,
setErrors,
setFieldError,
setFieldValue,
setValues,
setFieldTouched,
setTouched,
resetForm,
};
});
return function renderForm(this: any) {
// FIXME: Hacky but cute way to expose some stuff to the rendered instance
// getCurrentInstance doesn't work with render fns, it returns the wrong instance
// we want to expose setFieldError and setErrors
if (!('setErrors' in this)) {
this.setFieldError = setFieldError;
this.setErrors = setErrors;
this.setFieldValue = setFieldValue;
this.setValues = setValues;
this.setFieldTouched = setFieldTouched;
this.setTouched = setTouched;
this.resetForm = resetForm;
this.validate = validate;
this.validateField = validateField;
}
const children = normalizeChildren(ctx, slotProps.value);
if (!props.as) {
return children;
}
// Attributes to add on a native `form` tag
const formAttrs =
props.as === 'form'
? {
// Disables native validation as vee-validate will handle it.
novalidate: true,
}
: {};
return h(
// avoid resolving the form component as itself
props.as === 'form' ? props.as : (resolveDynamicComponent(props.as) as string),
{
...formAttrs,
...ctx.attrs,
onSubmit,
onReset: handleFormReset,
},
children
);
};
},
});