Commit caa734fae78f0ee2c630668d2d4927287d1f18c8

Authored by liuhanchen
1 parent 8104d35f

feat: 表格支持行内校验

packages/table/editor.vue
... ... @@ -37,49 +37,82 @@ function cellRender(h, context, item) {
37 37 };
38 38 }
39 39  
  40 +// 表单项渲染
  41 +function formItemRender(h, context, item, scope, children) {
  42 + // 渲染函数配置
  43 + const contentProps = context.props || {};
  44 + // 编辑器统一配置
  45 + const editorProps = get(contentProps, 'editor.props') || {};
  46 + let formItemProp = [editorProps.path].filter(i => i);
  47 + formItemProp.push(scope.$index);
  48 + formItemProp.push(item.prop);
  49 + formItemProp = formItemProp.join('.');
  50 + return h(
  51 + editorProps.formItem || 'el-form-item',
  52 + {
  53 + props: { prop: formItemProp, rules: item.rules, 'inline-message': true },
  54 + },
  55 + children,
  56 + );
  57 +}
  58 +
40 59 // 编辑器渲染
41 60 function editorRender(h, context, item) {
42 61 const editorSlot = context.scopedSlots[`editor-${item.prop}`];
43 62 const contentProps = context.props || {};
44 63 return function(scope) {
45 64 const value = get(scope.row, item.prop);
46   - // 自定义具名插槽
47   - if (editorSlot) {
48   - return editorSlot({ item, value, index: scope.$index, ...scope });
49   - }
  65 + let vnode = {};
50 66 // 默认
51   - const vnode = h(item.is, {
52   - attrs: item.attrs,
53   - props: { ...(item.props || {}), value },
54   - on: {
55   - input(val) {
56   - if (get(contentProps, 'editor.deep') === true) {
57   - if (item.prop.indexOf('.') > -1 || item.prop.indexOf('[') > -1) {
58   - let separator = '';
59   - if (item.prop.indexOf('.') > -1) {
60   - separator = '.';
61   - } else if (item.prop.indexOf('[') > -1) {
62   - separator = '[';
63   - }
64   - const path = item.prop.split(separator);
65   - const bindProp = path[0];
66   - const propValue = cloneDeep(scope.row);
67   - set(propValue, item.prop, val);
68   - vnode.componentInstance.$set(scope.row, bindProp, propValue[bindProp]);
69   - } else {
70   - // set(scope.row, item.prop, val);
71   - scope.row[item.prop] = val;
72   - }
73   - } else {
74   - scope.row[item.prop] = val;
75   - // set(contentProps.data, `[${[scope.$index]}]${item.prop}`, val);
  67 + const inputEvent = val => {
  68 + if (get(contentProps, 'editor.deep') === true) {
  69 + if (item.prop.indexOf('.') > -1 || item.prop.indexOf('[') > -1) {
  70 + let separator = '';
  71 + if (item.prop.indexOf('.') > -1) {
  72 + separator = '.';
  73 + } else if (item.prop.indexOf('[') > -1) {
  74 + separator = '[';
76 75 }
77   - if (item.on && item.on.input) {
78   - item.on.input(val);
79   - }
80   - },
81   - },
  76 + const path = item.prop.split(separator);
  77 + const bindProp = path[0];
  78 + const propValue = cloneDeep(scope.row);
  79 + set(propValue, item.prop, val);
  80 + vnode.componentInstance.$set(scope.row, bindProp, propValue[bindProp]);
  81 + } else {
  82 + // set(scope.row, item.prop, val);
  83 + scope.row[item.prop] = val;
  84 + }
  85 + } else {
  86 + scope.row[item.prop] = val;
  87 + // set(contentProps.data, `[${[scope.$index]}]${item.prop}`, val);
  88 + }
  89 + if (item.on && item.on.input) {
  90 + item.on.input(val);
  91 + }
  92 + };
  93 + const blurEvent = val => {
  94 + if (item.on && item.on.blur) {
  95 + item.on.blur(val);
  96 + }
  97 + };
  98 + // 编辑表单项配置
  99 + const itemProps = item.props || {};
  100 + // 编辑器统一配置
  101 + const editorProps = get(contentProps, 'editor.props') || {};
  102 + // 生成虚拟节点
  103 + vnode = h(item.is, {
  104 + attrs: item.attrs,
  105 + props: { ...editorProps, ...itemProps, value },
  106 + on: { input: inputEvent, blur: blurEvent },
82 107 });
  108 + // 自定义具名插槽
  109 + if (editorSlot) {
  110 + return editorSlot({ item, value, index: scope.$index, ...scope, onInput: inputEvent });
  111 + }
  112 + // 需要校验时外层嵌套校验组件
  113 + if (editorProps.validate) {
  114 + return formItemRender(h, context, item, scope, [vnode]);
  115 + }
83 116 return vnode;
84 117 };
85 118 }
... ... @@ -90,11 +123,18 @@ function createElTableColumns(h, context, columns) {
90 123 const editorConfig = props.editor || {};
91 124 return columns.map((item, index) => {
92 125 const { attrs, on, ...props } = item;
93   - const editorMatch = editorConfig.inputs.find(i => i.prop === item.prop);
  126 + const items = editorConfig.items || [];
  127 + // 当前列编辑器配置
  128 + let editorItem = items.find(i => i.prop === item.prop);
  129 + // 当前列有编辑器配置或编辑器插槽的情况
  130 + const isEditor = editorItem || context.scopedSlots[`editor-${item.prop}`];
  131 + if (context.scopedSlots[`editor-${item.prop}`] && !editorItem) {
  132 + editorItem = item;
  133 + }
94 134 // 处理插槽
95 135 const scopedSlots = {
96 136 header: headerRender(h, context, item),
97   - default: editorMatch ? editorRender(h, context, editorMatch) : cellRender(h, context, item),
  137 + default: isEditor ? editorRender(h, context, editorItem) : cellRender(h, context, item),
98 138 };
99 139 return h('el-table-column', { key: index, attrs, props, on, scopedSlots });
100 140 });
... ... @@ -106,6 +146,9 @@ export default {
106 146 render(h, context) {
107 147 console.log(context);
108 148 const props = context.props || {};
  149 + // 设置默认class名称,用来追加一些默认的样式
  150 + const className = get(context, 'data.class');
  151 + set(context, 'data.class', className ? `${className} z-table-editor` : 'z-table-editor');
109 152 let scopedSlots = context.scopedSlots || {};
110 153 // 如有默认插槽则相当于直接写el-table
111 154 if (scopedSlots.default) {
... ... @@ -128,3 +171,16 @@ export default {
128 171 },
129 172 };
130 173 </script>
  174 +
  175 +<style lang="scss">
  176 +.z-table-editor {
  177 + &.el-table td .cell {
  178 + padding-top: 2px !important;
  179 + padding-bottom: 2px !important;
  180 + padding-right: 2px !important;
  181 + }
  182 + .el-form-item {
  183 + margin-bottom: 0 !important;
  184 + }
  185 +}
  186 +</style>
... ...
packages/table/index.vue
... ... @@ -9,7 +9,7 @@ export default {
9 9 if (Object.prototype.hasOwnProperty.call(props, 'editable') && props.editable !== false) {
10 10 return h('z-table-editable', { props, scopedSlots: context.scopedSlots, on: context.listeners });
11 11 }
12   - if (props.editor) {
  12 + if (Object.prototype.hasOwnProperty.call(props, 'editor')) {
13 13 return ref('z-table-editor', context);
14 14 }
15 15 return ref('z-table-normal', context);
... ...