UNPKG

ng-layout-form

Version:

layout form

643 lines (641 loc) 26.1 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/form/index.tsx var form_exports = {}; __export(form_exports, { FormLayout: () => FormLayout }); module.exports = __toCommonJS(form_exports); var import_antd = require("antd"); var import_ng_base_stand = require("ng-base-stand"); var import_ng_lib_tsx = require("ng-lib-tsx"); var import_react = require("react"); var import_scroll_into_view_if_needed = __toESM(require("scroll-into-view-if-needed")); var import__ = require(".."); var import_useColspan = __toESM(require("../useColspan")); var import_util = require("../util/util"); var import_footer = __toESM(require("./footer")); var import_handleStyle = require("./handleStyle"); var import_index = require("./index.less"); var import_listener = require("./listener"); var import_renderLabel = __toESM(require("./renderLabel")); var import_viewItem = __toESM(require("./viewItem")); var import_volidRule = require("./volidRule"); var gutter = { xs: 8, sm: 16, md: 24, lg: 32 }; function isValueLabel(item) { return import_ng_lib_tsx.NG.isObject(item) && item.hasOwnProperty("value") && item.hasOwnProperty("label"); } function getObjPath(obj, p = []) { const prev = p.length > 0 ? p[p.length - 1] : ""; const tmpKey = Object.keys(obj)[0]; const tmpValue = tmpKey ? obj[tmpKey] : ""; const current = prev ? `${prev}.${tmpKey}` : tmpKey; if (import_ng_lib_tsx.NG.isObject(tmpValue) && Object.keys(tmpValue).length > 0) { return getObjPath(tmpValue, [...p, current]); } return [...p, current]; } function convertValues(initValues, fields) { const splitStr = ","; const fn = (items) => { items.forEach((field) => { var _a, _b; const item = { ...field, ...field.antProps }; if (item.xtype === "container") { fn(item.children || item.items); } else { const value = (0, import_util.getObjValue)(initValues, item.name); if (item.name) { const valueType = item.valueType; const xType = ((_b = (_a = item.xtype) == null ? void 0 : _a.toLowerCase) == null ? void 0 : _b.call(_a)) || ""; const nameField = item.nameField || (xType.endsWith("select") || xType.endsWith("help") ? `${item.name}_EXName` : ""); if (nameField && !import_ng_lib_tsx.NG.isNullOrEmpty(value, "")) { const nameFieldValue = (0, import_util.getObjValue)(initValues, nameField); const label = nameFieldValue ?? value; const tip = (0, import_util.getObjValue)(initValues, `${item.name}EXNameNew`) ?? (0, import_util.getObjValue)(initValues, `${item.name}_EXNameNew`) ?? ""; if (item.multiple || item.xtype === "NGMultipleHelp") { const tipArray = import_ng_lib_tsx.NG.isArray(tip) ? tip : tip ? tip.toString().split(splitStr) : []; const labelArray = import_ng_lib_tsx.NG.isArray(label) ? label : label ? label.toString().split(splitStr) : []; const valueArray = import_ng_lib_tsx.NG.isArray(value) ? value : value.toString().split(splitStr); const valueLabel = valueArray.map((v, i) => { return (v == null ? void 0 : v.hasOwnProperty("value")) ? { tip: tipArray[i], ...v } : { value: import_ng_lib_tsx.NG.convertData(v, valueType), label: labelArray[i] ?? v, tip: tipArray[i] }; }).filter(({ label: label2 }) => !import_ng_lib_tsx.NG.isNullOrEmpty(label2, "")); (0, import_util.setObjValue)(initValues, item.name, valueLabel.length ? valueLabel : null); } else { (0, import_util.setObjValue)( initValues, item.name, value.hasOwnProperty("value") ? { tip, ...value } : { value: import_ng_lib_tsx.NG.convertData(value, valueType), label, tip } ); } } else { (0, import_util.setObjValue)(initValues, item.name, import_ng_lib_tsx.NG.convertData(value, valueType, item.format)); } } } }); }; fn(fields); return initValues; } function FormLayoutComp(cmpProps) { const [props, children] = (0, import_ng_lib_tsx.useDevState)({ type: "form", id: cmpProps["id"] || cmpProps["data-cid"] || "form", props: cmpProps, items: cmpProps.formConf.children, itemKey: "name" }); const formConf = (0, import_react.useMemo)(() => ({ ...cmpProps.formConf, children }), [cmpProps.formConf, children]); const { formSetRef, design, initSc, footerProps, opt, dataId = "PhId", defaultValue: dv, value, disabled, outRef, rules, style: formStyle, className: defaultFormClassName, bordered: defaultBordered, onLoad, disabledNotify = false, colon: defaultColon } = props; const fields = (0, import_react.useMemo)(() => { const fn = (items, pname = "") => { return items.map((item) => { const tmp = { ...item }; if (tmp.xtype === "container") { tmp.children = fn(tmp.children || tmp.items, tmp.name); delete tmp.name; } else if (import_ng_lib_tsx.NG.isString(tmp.name) && pname) { tmp.name = [pname, tmp.name]; } return tmp; }); }; return fn(formConf.children || []); }, [formConf.children]); const isChange = (0, import_react.useRef)(false); const defaultValue = (0, import_react.useMemo)( () => convertValues((0, import__.getInitVals)({ children: fields }, "form", value || dv) || {}, fields), [value, dv] ); const initValue = (0, import_react.useMemo)(() => import_ng_lib_tsx.NG.deepCopy(defaultValue), []); const colspan = formConf.colspan ?? props.colspan; const labelPosition = formConf.labelPosition ?? (props.labelPosition || "left"); const formLayout = formConf.layout ?? (props.layout || (labelPosition === "top" ? "vertical" : "horizontal")); const cacheItems = (0, import_react.useMemo)(() => ({}), [formConf]); const [form] = import_antd.Form.useForm(); const [dspan, setDspan] = (0, import_react.useState)(import_ng_lib_tsx.NG.isNumber(colspan) ? 24 / colspan : 8); const gDisabled = formConf.disabled ?? disabled; const { query } = import_ng_lib_tsx.history.location; const optType = opt || query["opt"]; const labelWidth = formConf.labelWidth || props.labelWidth || import_ng_lib_tsx.cssVar.formLabelWidth; const [m, setM] = (0, import_react.useState)({}); const bordered = formConf.bordered ?? defaultBordered; const colon = bordered ? false : formConf.colon ?? defaultColon ?? true; const isView = formConf.view ?? props.view; const formClassName = import_ng_lib_tsx.NG.classNames( "ng-form-wrapper", defaultFormClassName, bordered ? "ng-bordered-form" : "", isView ? "ng-view-form" : "" ); const mergeHandler = (0, import_react.useMemo)( () => (0, import_listener.mergeEventHandler)(() => { setM((m2) => ({ ...m2 })); }), [] ); const handlers = mergeHandler(); const containerId = `${props.id || props["data-cid"] || formConf.name || "form"}`; const { breakPairs, breakPoints, setBreakPairs } = (0, import_useColspan.default)(containerId, colspan); const labelAlign = props.labelAlign || formConf.labelAlign || "right"; (0, import_react.useEffect)(() => { onLoad == null ? void 0 : onLoad(); outRef.current._compIns.getObserver().prevNotify({ ins: outRef.current }, "onLoad").then(); }, [formConf]); (0, import_react.useEffect)(() => { mergeHandler(initSc, true); }, [initSc]); (0, import_react.useEffect)(() => { setM((0, import_volidRule.mergeRules)((0, import_volidRule.initRules)({ children: fields }), rules)); }, [fields, rules]); const syncValues = (changedValues) => { import_ng_lib_tsx.NG.deepMerge(defaultValue, changedValues); }; (0, import_react.useEffect)(() => { form.setFieldsValue(defaultValue); }, [defaultValue]); const rewriteFormApi = { resetFields() { isChange.current = true; syncValues(initValue); form.resetFields(); }, setFieldsValue(values) { isChange.current = true; syncValues(values); form.setFieldsValue(defaultValue); }, setFieldValue(name, value2) { rewriteFormApi.setFieldsValue({ [name]: value2 }); }, scrollToField(name, options = {}) { const node = document.querySelector(`[data-cid="${containerId}_${name}"]`); node && (0, import_scroll_into_view_if_needed.default)(node, { scrollMode: "if-needed", block: "center", ...options }); } }; const validData = () => { return form.validateFields().then( () => true, ({ errorFields }) => { const namePath = errorFields[0].name.join("_"); rewriteFormApi.scrollToField(namePath); return false; } ); }; (0, import_ng_lib_tsx.useExtendRef)(outRef, { ...form, ...rewriteFormApi, isChanged: () => isChange.current, setModel: setM, clear: () => { Object.keys(defaultValue).forEach((key) => { defaultValue[key] = void 0; }); form.setFieldsValue(defaultValue); }, getFormatValues, getValues: (mergeValues = true, undefinedValue = "") => beforeSubmit({ mergeValues, undefinedValue }), changeFormValues: (values = {}) => rewriteFormApi.setFieldsValue(values), mergeRules: (newRule) => setM((m2) => (0, import_volidRule.mergeRules)(m2, newRule)), mergeHandler, isValid: validData, validData, validateForm: form.validateFields, getItem: (name) => { var _a, _b; return (_b = (_a = form.getFieldInstance(name)) == null ? void 0 : _a.getApi) == null ? void 0 : _b.call(_a); }, setBreakPairs, setHidden: (name, hidden = true) => { setConfigByName(name, { hidden }); }, setRequired: (name, required = true) => { setConfigByName(name, { required }); }, getConfig: () => formConf, setConfig, setConfigByName, getDspan: () => dspan, focus: () => { focusItem(fields); function focusItem(items) { var _a, _b, _c; for (let index = 0; index < items.length; index++) { const element = items[index]; if (Array.isArray(element.children) && focusItem(element.children)) { return true; } if (element.disabled || element.hidden) { } else { const item = (_b = (_a = form.getFieldInstance(element.name)) == null ? void 0 : _a.getApi) == null ? void 0 : _b.call(_a); if (item == null ? void 0 : item.focus) { (_c = item == null ? void 0 : item.focus) == null ? void 0 : _c.call(item); return true; } } } return false; } }, subscribe: (0, import_util.getSubscribeFn)(outRef), setReadOnly(name = true, disabled2 = true) { if (import_ng_lib_tsx.NG.isBoolean(name)) { import_ng_lib_tsx.NG.fastDp.form.updateProps({ id: containerId, props: { disabled: disabled2 } }); } else { setConfigByName(name, { disabled: disabled2 }); } } }); const _renderItem = (0, import_ng_lib_tsx.useRefCallback)((item, index) => { var _a, _b, _c, _d; const key = item.name || item.itemId || index; if (item.hidden) return ""; let cellStyle = { paddingLeft: 0, paddingRight: 0 }; formLayout === "inline" && (cellStyle["with"] = formConf.minWidth || 300); let span = getColspan(item.colspan) || 1; if (["ngattachment", "attachment", "htmleditor", "nghtmleditor"].includes((_b = (_a = item.xtype) == null ? void 0 : _a.toLowerCase) == null ? void 0 : _b.call(_a)) && item.mode !== "button") { span = 24; } if (!item.status && ["ngattachment", "attachment"].includes((_d = (_c = item.xtype) == null ? void 0 : _c.toLowerCase) == null ? void 0 : _d.call(_c))) { item.status = import_ng_lib_tsx.NG.getQueryValue("oType"); } return /* @__PURE__ */ React.createElement(import_antd.Col, { key, style: cellStyle, "data-id": key, span }, renderFormItem(item, index)); function renderFormItem(item2, index2) { item2 = item2 || {}; const { instance: Comp } = (0, import_util.getComp)(item2); if (Comp === "NGGroup") { return /* @__PURE__ */ React.createElement("div", { className: "nggroup", style: { display: item2.hidden ? "none" : "flex" }, key: item2.name || index2 }, renderGroup(item2, index2)); } else { return renderFI(item2, index2); } } function renderFI(item2, index2) { const { instance: Comp, props: defaultProps } = isView ? { instance: import_viewItem.default } : (0, import_util.getComp)(item2); const listener = (handlers.children || {})[item2.name] || {}; let rules2 = m[item2.name] || []; const dp = filterProps(item2); const disabled2 = item2.disabled ?? gDisabled; disabled2 && (dp["disabled"] = !!disabled2); const clientSqlFilter = dp.clientSqlFilter; if (import_ng_lib_tsx.NG.isFunction(clientSqlFilter)) { dp.clientSqlFilter = (args) => clientSqlFilter({ ...args, form: outRef.current }); } "getPopupContainer" in dp && (dp["getPopupContainer"] = getPopupContainer); const { onChange, ...others } = { ...dp, ...listener }; bordered && (others.bordered = false); if (!item2.hasOwnProperty("extra") && ["InputNumber", "Input", "NGInputNumber"].includes(item2.xtype) && ["percent", "rate"].includes(item2.type)) { item2.extra = "%"; } const getItemProps = () => { const p = { label: item2.label ? /* @__PURE__ */ React.createElement( import_renderLabel.default, { width: labelPosition === "top" ? "100%" : item2.labelWidth || labelWidth, label: item2.label, langKey: item2.langKey, labelAlign } ) : "", labelAlign, className: `item-checked-customer formItem ${!item2.label && "form-item-nolabel" || ""}`, key: item2.name || index2, required: item2.required, style: item2.style }; if (!item2.extra) { p.rules = rules2; p.name = item2.name || index2; } if (item2.dependencies) { p.dependencies = item2.dependencies; } return p; }; const getItemCmp = () => { return /* @__PURE__ */ React.createElement(Comp, { ...isView ? { "data-item": item2 } : {}, ...others, ...defaultProps }); }; return /* @__PURE__ */ React.createElement(import_antd.Form.Item, { ...getItemProps() }, item2.extra ? /* @__PURE__ */ React.createElement("div", { style: { display: "flex", flexDirection: "row", alignItems: "center", gap: 6 } }, /* @__PURE__ */ React.createElement(import_antd.Form.Item, { name: item2.name, noStyle: true, style: { flex: 1, minWidth: 0 }, rules: rules2 }, getItemCmp()), item2.extra) : getItemCmp()); } function renderGroup(item2, index2) { const items = item2.children || item2.items || []; if (item2.customerStyle) { return /* @__PURE__ */ React.createElement("div", { style: item2.customerStyle }, items.map((it) => renderFI(it, index2))); } else { const noColToFormStyle = { display: "flex", width: "100%", marginBottom: 0, ...item2.style || {} }; return /* @__PURE__ */ React.createElement( import_antd.Form.Item, { label: item2.label && /* @__PURE__ */ React.createElement(import_renderLabel.default, { width: item2.labelWidth || labelWidth, label: item2.label, labelAlign }), className: `item-checked-customer formItem formContainerItem`, style: noColToFormStyle, required: item2.required }, items.map((it) => renderFI(it, index2)) ); } } }); const _renderForm = (0, import_react.useMemo)(() => { return fields.map(_renderItem); }, [fields, formConf, m, dspan, gDisabled, labelPosition]); const fstyle = (0, import_react.useMemo)(() => (0, import_handleStyle.getFormStyle)(formConf), [formConf]); const hasBorderStyle = bordered || formConf.bordered ? "border-form" : ""; const className = (0, import_react.useMemo)(() => import_ng_lib_tsx.NG.classNames("ng-form", formLayout, hasBorderStyle), [design]); const formHandler = { ...handlers }; delete formHandler.children; const getDspan = (0, import_ng_lib_tsx.useRefCallback)(({ width }) => { let index = breakPoints.findIndex((item) => { return item > width; }); index = index === -1 ? breakPoints.length - 1 : index; const defaultSpan = 24 / breakPairs[breakPoints[index]]; if (dspan !== defaultSpan) { setDspan(defaultSpan || 4); } }); async function dealPropsChange(changedValues, allValues, oldValues) { const changedEvent = props.onValuesChange || handlers["onValuesChange"]; const res = await (changedEvent == null ? void 0 : changedEvent(changedValues, allValues)); if (res === false) { rewriteFormApi.setFieldsValue(oldValues); } else if (import_ng_lib_tsx.NG.isObject(res)) { syncValues(res); if (res !== changedValues) { rewriteFormApi.setFieldsValue(defaultValue); } } return res !== false; } const notify = (0, import_ng_base_stand.useDebounce)( (updateValue) => { import_ng_lib_tsx.NG.getPageObserver().notify( { key: getObjPath(updateValue), containerId: props["cid"] || containerId, form: outRef.current, args: [updateValue, defaultValue] }, "onValuesChange" ); }, { wait: 250 } ); function handleValuesChange(changedValues, allValues) { const oldValues = import_ng_lib_tsx.NG.deepCopy(defaultValue); isChange.current = true; const updateValue = changedValues; syncValues(updateValue); dealPropsChange(changedValues, allValues, oldValues).then((success) => { var _a, _b, _c; const listener = handlers.children || {}; Object.keys(updateValue).forEach((key) => { var _a2; const dp = filterProps(getFormItem(key) || {}); const onChange = dp.onChange || ((_a2 = listener[key]) == null ? void 0 : _a2.onChange); if (onChange && updateValue[key] !== oldValues[key]) { onChange(updateValue[key], oldValues[key]); } }); if (success && !disabledNotify) { (_b = (_a = outRef.current).innerNotify) == null ? void 0 : _b.call(_a, [updateValue, defaultValue], "onValuesChange"); (_c = formSetRef == null ? void 0 : formSetRef.current) == null ? void 0 : _c.innerNotify([updateValue, defaultValue], "onValuesChange"); notify(updateValue); } }); } return /* @__PURE__ */ React.createElement("div", { id: `${containerId}_ctx`, style: { position: "relative" } }, /* @__PURE__ */ React.createElement(import_ng_lib_tsx.AutoResize, { onResize: getDspan }, /* @__PURE__ */ React.createElement( import_antd.Form, { name: containerId, ...handlers, onValuesChange: handleValuesChange, form, style: formStyle, layout: formLayout, className: formClassName, colon }, /* @__PURE__ */ React.createElement(import_antd.Row, { className, style: fstyle, gutter }, _renderForm), /* @__PURE__ */ React.createElement( import_footer.default, { footerProps, onSave, onReset, onCheck: form.validateFields, disabled: gDisabled } ) ))); function onSave() { props.onSave && props.onSave(getFormatValues(), form.getFieldsError()); } function getFormatValues(initValues = {}) { const id = dataId || "PhId"; const data = { ...initValues, ...beforeSubmit() }; const opt2 = optType || ((data == null ? void 0 : data[id]) ? "modifiedRow" : "newRow"); return (0, import_util.fomatValues)(formConf.name, "form", opt2, dataId, data)()[formConf.name]; } function beforeSubmit({ mergeValues = true, undefinedValue = "" } = {}) { let initValues = form.getFieldsValue(); const fn = (items) => { items.forEach((field) => { const item = { ...field, ...field.antProps }; const originValue = (0, import_util.getObjValue)(initValues, item.name); if (item.name && !item.hidden) { if (field.xtype === "container") { fn(field.children || field.items); } else { const nameField = item.nameField; const emptyValue = item.emptyValue ?? undefinedValue; if (Array.isArray(originValue)) { if (originValue.length > 0 && isValueLabel(originValue[0])) { (0, import_util.setObjValue)(initValues, item.name, originValue.map((item2) => item2.value).join()); nameField && (0, import_util.setObjValue)(initValues, nameField, originValue.map((item2) => item2.label).join()); } else if (originValue.length === 0) { (0, import_util.setObjValue)(initValues, item.name, emptyValue); nameField && (0, import_util.setObjValue)(initValues, nameField, ""); } } else if (isValueLabel(originValue)) { (0, import_util.setObjValue)(initValues, item.name, originValue.value); nameField && (0, import_util.setObjValue)(initValues, nameField, originValue.label); } if ((0, import_util.getObjValue)(initValues, item.name) === void 0) { (0, import_util.setObjValue)(initValues, item.name, emptyValue); } } } }); }; fn(fields); return mergeValues ? { ...defaultValue, ...initValues } : initValues; } function onReset() { props.onReset && props.onReset(); form.resetFields(); } function getPopupContainer() { return props.getPopupContainer ? props.getPopupContainer() : document.getElementById(`${containerId}_ctx`); } function getColspan(itemColspan) { if (itemColspan === void 0 || itemColspan === null) { return dspan; } const cs = itemColspan * dspan; return cs > 24 ? 24 : Math.round(cs); } function getFormItem(key, formItems) { if (cacheItems[key]) return cacheItems[key]; formItems = formItems || fields; for (let i = 0; i < formItems.length; i++) { const item = formItems[i]; if (item.name === key) { cacheItems[key] = item; return item; } const items = item.children || item.items || []; if (items.length) { const tmp = getFormItem(key, items); if (tmp) { return tmp; } } } } function setConfig(config) { const prevConfig = [...formConf.children]; if (import_ng_lib_tsx.NG.isFunction(config)) { const newConfig = config(prevConfig); newConfig && import_ng_lib_tsx.NG.fastDp.form.setItems({ id: containerId, items: newConfig }); } else { let isUpdated = false; Object.keys(config).forEach((name) => { const item = prevConfig.find((item2) => { const itemName = import_ng_lib_tsx.NG.isArray(item2.name) ? item2.name.join(".") : item2.name; return itemName === name; }); if (item) { Object.assign(item, config[name]); isUpdated = true; } }); isUpdated && import_ng_lib_tsx.NG.fastDp.form.setItems({ id: containerId, items: prevConfig }); } } function setConfigByName(name, config) { const keys = import_ng_lib_tsx.NG.isArray(name) ? name : [name]; setConfig( keys.reduce((p, c) => { p[c] = config; return p; }, {}) ); } } var common_props = /* @__PURE__ */ new Set([ "name", "label", // 'placeholder', "defaultValue", "required", "disabled", "colspan", "langKey" ]); function filterProps(item) { let dp = Object.keys(item).reduce((acc, key) => { if (!common_props.has(key)) { acc[key] = item[key]; } return acc; }, {}); delete dp.style; delete dp.nameField; delete dp.extra; delete dp.dependencies; dp = { ...dp, ...dp.antProps }; delete dp["antProps"]; delete dp.customRule; delete dp.onlyRequiredStyle; delete dp.rules; delete dp.defaultValue; delete dp.valueType; delete dp.emptyValue; delete dp.xtype; delete dp.labelWidth; return dp; } var FormLayout = (0, import_ng_lib_tsx.compHoc)( (0, import_util.LayConfWrap)(FormLayoutComp), "NGForm" ); (0, import_ng_lib_tsx.registerComponent)({ FormLayout }); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { FormLayout });