@progress/kendo-vue-form
Version:
295 lines (294 loc) • 9.15 kB
JavaScript
/**
* @license
*-------------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the package root for more information
*-------------------------------------------------------------------------------------------
*/
import { validatePackage as h, clone as l, cloneObject as u, canUseDOM as a, guid as n, getDefaultSlots as f } from "@progress/kendo-vue-common";
import { packageMetadata as m } from "./package-metadata.mjs";
import { defineComponent as c } from "vue";
const F = 0, B = /* @__PURE__ */ c({
name: "KendoForm",
inheritAttrs: !1,
props: {
renderForm: [Object, Function],
initialValues: Object,
validator: Function,
ignoreModified: Boolean
},
emits: {
submitclick: null,
submit: null
},
created() {
this._accumulatorTimeout = void 0, h(m), this.form.values = l(this.$props.initialValues);
},
mounted() {
this.form.errors = this.getErrors(), this.form.allowSubmit = this.allowSubmit(), this.form.valid = this.isValid();
},
unmounted() {
this.onDestroy();
},
data() {
return {
validatorsByField: {},
fields: [],
unmounted: !1,
form: {
id: this.id,
errors: {},
values: {},
modifiedByField: {},
touchedByField: {},
visitedByField: {},
valid: !1,
modified: !1,
touched: !1,
visited: !1,
submitted: !1,
valueGetter: this.valueGetter,
allowSubmit: !1,
validate: this.validate,
onChange: this.onChange,
onSubmit: this.onSubmit,
onFormReset: this.resetForm,
registerField: this.onFieldRegister,
onFocus: this.onFocus,
onBlur: this.onBlur,
onUnshift: this.onUnshift,
onPush: this.onPush,
onInsert: this.onInsert,
onPop: this.onPop,
onRemove: this.onRemove,
onReplace: this.onReplace,
onMove: this.onMove
}
};
},
provide() {
return {
kendoForm: this.$data.form
};
},
watch: {
"form.values"() {
this.form.errors = this.getErrors(), this.form.allowSubmit = this.allowSubmit(), this.form.valid = this.isValid();
},
"form.touchedByField"(i) {
this.form.touched = this.isFormTouched(i, this.fields), this.form.allowSubmit = this.allowSubmit();
},
"form.modifiedByField"(i) {
this.form.modified = this.isFormModified(i, this.fields), this.form.allowSubmit = this.allowSubmit();
},
"form.visitedByField"(i) {
this.form.visited = this.isFormVisited(i, this.fields);
}
},
methods: {
isValid() {
return this.isFormValid(this.form.errors);
},
formErrors() {
if (this.$props.validator)
return this.$props.validator(this.form.values, this.valueGetter);
},
getErrors() {
const i = {}, t = this.validatorsByField;
return Object.keys(this.fields).forEach((s) => {
if (i[s] = "", t[s]) {
const r = [];
t[s].forEach((o) => {
Array.isArray(o) ? r.push(...o) : r.push(o);
}), r.find((o) => {
if (o) {
const d = o(this.valueGetter(s), this.valueGetter, {
name: s
});
if (d)
return i[s] = d, !0;
}
return !1;
});
}
}), this.formErrors() && u(this.formErrors(), i), i;
},
/**
* @hidden
*/
accumulatedForceUpdate() {
this._accumulatorTimeout && clearTimeout(this._accumulatorTimeout), a && (this._accumulatorTimeout = window.setTimeout(() => {
this._accumulatorTimeout = void 0;
}, F));
},
/**
* @hidden
*/
resetForm() {
this.form.values = l(this.$props.initialValues), this.id = n(), this.form.touchedByField = {}, this.form.visitedByField = {}, this.form.modifiedByField = {}, this.form.submitted = !1;
},
/**
* Method for resetting the form state outside the form component.
*
* > Use `onReset` only if you cannot achieve the desired behavior
* through the Field component or by FormRenderProps.
*/
onReset() {
this.resetForm();
},
addField(i) {
this.fields[i] = !0;
},
validate(i) {
const t = {}, e = i || this.fields;
Object.keys(e).forEach((s) => {
t[s] = !0;
}), this.form.touchedByField = {
...t
};
},
onSubmit(i) {
const t = {}, e = this.fields;
i && (typeof i.preventDefault == "function" && i.preventDefault(), typeof i.stopPropagation == "function" && i.stopPropagation()), Object.keys(e).forEach((d) => {
t[d] = !0;
}), this.form.visitedByField = {
...t
}, this.form.touchedByField = {
...t
};
const s = this.form.values, r = this.isValid(), o = this.isFormModified(this.form.modifiedByField, e);
this.$emit("submitclick", {
values: s,
isValid: r,
isModified: o,
event: i
}), r && (this.$props.ignoreModified || o) && (this.form.submitted = !0, this.$emit("submit", s, i));
},
/**
* Method for emitting changes to a specific field outside the form component.
*
* > Use `onChange` only if you cannot achieve the desired behavior
* through the Field component by FormRenderProps.
*/
onChange(i, t) {
const {
value: e
} = t;
this.addField(i), this.form.modifiedByField[i] || (this.form.modifiedByField = {
...this.form.modifiedByField,
[i]: !0
}), this.valueSetter(i, e);
},
onFocus(i) {
this.form.visitedByField[i] || (this.form.visitedByField = {
...this.form.visitedByField,
[i]: !0
});
},
onBlur(i) {
this.form.touchedByField[i] || (this.onFocus(i), this.form.touchedByField = {
...this.form.touchedByField,
[i]: !0
});
},
onFieldRegister(i, t) {
this.addField(i);
const e = this.validatorsByField[i] || [], s = e.length;
return this.validatorsByField = {
...this.validatorsByField,
[i]: [...e, t]
}, this.accumulatedForceUpdate(), () => {
if (this._unmounted)
return;
const r = [...this.validatorsByField[i] || []], o = !!r[s];
r[s] = void 0, this.validatorsByField = {
...this.validatorsByField,
[i]: r
}, o && this.accumulatedForceUpdate();
};
},
isFormValid(i) {
return !Object.keys(i).some((t) => !!i[t]);
},
isFormModified(i, t) {
return Object.keys(t).some((e) => i[e]);
},
isFormHasNotTouched(i, t) {
return Object.keys(t).some((e) => !i[e]);
},
isFormTouched(i, t) {
return Object.keys(t).some((e) => i[e]);
},
isFormVisited(i, t) {
return Object.keys(t).some((e) => i[e]);
},
formHasNotTouched() {
return this.isFormHasNotTouched(this.form.touchedByField, this.fields);
},
// 1. The form is not touched, but has errors - allow submit to force validation.
// 2. The form is valid and modified - if not modified, disable submit.
allowSubmit() {
return this.formHasNotTouched() && !this.isValid() || this.isValid() && (this.$props.ignoreModified || this.isFormModified(this.form.modifiedByField, this.fields));
},
valueGetter(i) {
return this.form.values[i];
},
valueSetter(i, t) {
this.form.values = {
...this.form.values,
[i]: t
};
},
onArrayAction(i) {
this.addField(i), this.form.modifiedByField[i] || (this.form.modifiedByField = {
...this.form.modifiedByField,
[i]: !0
}), this.onBlur(i, !0);
},
onInsert(i, t) {
this.onArrayAction(i);
const e = [...this.valueGetter(i) || []];
e.splice(t.index, 0, t.value), this.valueSetter(i, e);
},
onUnshift(i, t) {
this.onInsert(i, {
value: t.value,
index: 0
});
},
onPush(i, t) {
this.onArrayAction(i);
const e = [...this.valueGetter(i) || [], t.value];
this.valueSetter(i, e);
},
onPop(i) {
this.onArrayAction(i);
const t = [...this.valueGetter(i) || []], e = t.pop();
return this.valueSetter(i, t), e;
},
onRemove(i, t) {
this.onArrayAction(i);
const e = [...this.valueGetter(i) || []], s = e.splice(t.index, 1);
return this.valueSetter(i, e), s;
},
onReplace(i, t) {
this.onArrayAction(i);
const e = [...this.valueGetter(i) || []];
e.splice(t.index, 1, t.value), this.valueSetter(i, e);
},
onMove(i, t) {
this.onArrayAction(i);
const e = [...this.valueGetter(i) || []], s = e[t.prevIndex];
e.splice(t.prevIndex, 1), e.splice(t.nextIndex, 0, s), this.valueSetter(i, e);
},
onDestroy() {
this.unmounted = !0, this._accumulatorTimeout && clearTimeout(this._accumulatorTimeout);
}
},
render() {
return f(this);
}
});
export {
B as Form
};