winbox-ui-next
Version:
We Design Vue 2.0: A Vue.js 3 UI Library
246 lines (245 loc) • 6.71 kB
JavaScript
import { defineComponent, toRefs, computed, reactive, provide, openBlock, createElementBlock, normalizeClass, withModifiers, renderSlot } from "vue";
import { formInjectionKey } from "./context.js";
import { getPrefixCls } from "../_utils/global-config.js";
import { isFunction, isArray } from "../_utils/is.js";
import { useSize } from "../_hooks/use-size.js";
import _export_sfc from "../_virtual/plugin-vue_export-helper";
const _sfc_main = defineComponent({
name: "Form",
props: {
model: {
type: Object,
required: true
},
layout: {
type: String,
default: "horizontal"
},
size: {
type: String
},
labelColProps: {
type: Object,
default: () => ({ span: 5, offset: 0 })
},
wrapperColProps: {
type: Object,
default: () => ({ span: 19, offset: 0 })
},
labelColStyle: Object,
wrapperColStyle: Object,
labelAlign: {
type: String,
default: "right"
},
disabled: {
type: Boolean,
default: void 0
},
rules: {
type: Object
},
autoLabelWidth: {
type: Boolean,
default: false
}
},
emits: {
submit: (data, ev) => true,
submitSuccess: (values, ev) => true,
submitFailed: (data, ev) => true
},
setup(props, { emit }) {
const prefixCls = getPrefixCls("form");
const {
model,
layout,
disabled,
labelAlign,
labelColProps,
wrapperColProps,
labelColStyle,
wrapperColStyle,
size,
rules
} = toRefs(props);
const { mergedSize } = useSize(size);
const autoLabelWidth = computed(() => props.layout === "horizontal" && props.autoLabelWidth);
const fields = [];
const touchedFields = [];
const labelWidth = reactive({});
const maxLabelWidth = computed(() => Math.max(...Object.values(labelWidth)));
const addField = (formItemInfo) => {
if (formItemInfo && formItemInfo.field) {
fields.push(formItemInfo);
}
};
const removeField = (formItemInfo) => {
if (formItemInfo && formItemInfo.field) {
fields.splice(fields.indexOf(formItemInfo), 1);
}
};
const setFields = (data) => {
fields.forEach((field) => {
if (data[field.field]) {
field.setField(data[field.field]);
}
});
};
const setLabelWidth = (width, uid) => {
if (uid && labelWidth[uid] !== width) {
labelWidth[uid] = width;
}
};
const removeLabelWidth = (uid) => {
if (uid) {
delete labelWidth[uid];
}
};
const resetFields = (field) => {
const _fields = field ? [].concat(field) : [];
fields.forEach((field2) => {
if (_fields.length === 0 || _fields.includes(field2.field)) {
field2.resetField();
}
});
};
const clearValidate = (field) => {
const _fields = field ? [].concat(field) : [];
fields.forEach((field2) => {
if (_fields.length === 0 || _fields.includes(field2.field)) {
field2.clearValidate();
}
});
};
const validate = (callback) => {
const list = [];
fields.forEach((field) => {
list.push(field.validate());
});
return Promise.all(list).then((result) => {
const errors = {};
let hasError = false;
result.forEach((item) => {
if (item) {
hasError = true;
errors[item.field] = item;
}
});
if (isFunction(callback)) {
callback(hasError ? errors : void 0);
}
return hasError ? errors : void 0;
});
};
const validateField = (field, callback) => {
const list = [];
for (const ctx of fields) {
if (isArray(field) && field.includes(ctx.field) || field === ctx.field) {
list.push(ctx.validate());
}
}
return Promise.all(list).then((result) => {
const errors = {};
let hasError = false;
result.forEach((item) => {
if (item) {
hasError = true;
errors[item.field] = item;
}
});
if (isFunction(callback)) {
callback(hasError ? errors : void 0);
}
return hasError ? errors : void 0;
});
};
const handleSubmit = (e) => {
const list = [];
fields.forEach((field) => {
list.push(field.validate());
});
Promise.all(list).then((result) => {
const errors = {};
let hasError = false;
result.forEach((item) => {
if (item) {
hasError = true;
errors[item.field] = item;
}
});
if (hasError) {
emit("submitFailed", { values: model.value, errors }, e);
} else {
emit("submitSuccess", model.value, e);
}
emit("submit", { values: model.value, errors: hasError ? errors : void 0 }, e);
});
};
provide(formInjectionKey, reactive({
layout,
disabled,
labelAlign,
labelColProps,
wrapperColProps,
labelColStyle,
wrapperColStyle,
model,
size: mergedSize,
rules,
fields,
touchedFields,
addField,
removeField,
validateField,
setLabelWidth,
removeLabelWidth,
maxLabelWidth,
autoLabelWidth
}));
const cls = computed(() => [
prefixCls,
`${prefixCls}-layout-${props.layout}`,
`${prefixCls}-size-${mergedSize.value}`,
{
[`${prefixCls}-auto-label-width`]: props.autoLabelWidth
}
]);
return {
cls,
handleSubmit,
innerValidate: validate,
innerValidateField: validateField,
innerResetFields: resetFields,
innerClearValidate: clearValidate,
innerSetFields: setFields
};
},
methods: {
validate(callback) {
return this.innerValidate(callback);
},
validateField(field, callback) {
return this.innerValidateField(field, callback);
},
resetFields(field) {
return this.innerResetFields(field);
},
clearValidate(field) {
return this.innerClearValidate(field);
},
setFields(data) {
return this.innerSetFields(data);
}
}
});
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return openBlock(), createElementBlock("form", {
class: normalizeClass(_ctx.cls),
onSubmit: _cache[0] || (_cache[0] = withModifiers((...args) => _ctx.handleSubmit && _ctx.handleSubmit(...args), ["prevent"]))
}, [
renderSlot(_ctx.$slots, "default")
], 34);
}
var _Form = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
export { _Form as default };