UNPKG

@progress/kendo-vue-form

Version:
295 lines (294 loc) 9.15 kB
/** * @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 };