UNPKG

7.92 kBJavaScriptView Raw
1import getConfig from './config';
2import mergeProps from '@form-create/utils/lib/mergeprops';
3import is, {hasProperty} from '@form-create/utils/lib/type';
4import toString from '@form-create/utils/lib/tostring';
5import extend from '@form-create/utils/lib/extend';
6
7function isTooltip(info) {
8 return info.type === 'tooltip';
9}
10
11const upperCaseReg = /[A-Z]/;
12
13export function isAttr(name, value) {
14 return (!upperCaseReg.test(name) && (is.String(value) || is.Number(value)))
15}
16
17function tidy(props, name) {
18 if (!hasProperty(props, name)) return;
19 if (is.String(props[name])) {
20 props[name] = {[name]: props[name], show: true};
21 }
22}
23
24function isFalse(val) {
25 return val === false;
26}
27
28function tidyBool(opt, name) {
29 if (hasProperty(opt, name) && !is.Object(opt[name])) {
30 opt[name] = {show: !!opt[name]};
31 }
32}
33
34export default {
35 validate(call) {
36 this.form().validate(call);
37 },
38 validateField(field, call) {
39 this.form().validateField(field, call);
40 },
41 clearValidateState(ctx) {
42 const fItem = this.vm.$refs[ctx.wrapRef];
43 if (fItem) {
44 fItem.validateMessage = '';
45 fItem.validateState = '';
46 }
47 },
48 tidyOptions(options) {
49 ['submitBtn', 'resetBtn', 'row', 'info', 'wrap', 'col'].forEach(name => {
50 tidyBool(options, name);
51 })
52 return options;
53 },
54 tidyRule({prop}) {
55 tidy(prop, 'title');
56 tidy(prop, 'info');
57 return prop;
58 },
59 mergeProp(ctx) {
60 let props = ctx.prop.props;
61 ctx.prop = mergeProps([{
62 attrs: Object.keys(props).reduce((initial, val) => {
63 if (isAttr(val, props[val]))
64 initial[val] = props[val];
65 return initial;
66 }, {}),
67 info: this.options.info || {},
68 wrap: this.options.wrap || {},
69 col: this.options.col || {},
70 }, ctx.prop], {
71 info: {
72 trigger: 'hover',
73 placement: 'top-start',
74 icon: 'el-icon-warning',
75 },
76 title: {},
77 col: {span: 24},
78 wrap: {},
79 }, {normal: ['title', 'info', 'col', 'wrap']});
80 },
81 getDefaultOptions() {
82 return getConfig();
83 },
84 update() {
85 const form = this.options.form;
86 this.rule = {
87 props: {...form},
88 nativeOn: {
89 submit: (e) => {
90 e.preventDefault();
91 }
92 },
93 class: [form.className, form.class, 'form-create'],
94 style: form.style,
95 type: 'form',
96 };
97 },
98 beforeRender() {
99 const {key, ref, $handle} = this;
100 extend(this.rule, {key, ref});
101 extend(this.rule.props, {
102 model: $handle.formData,
103 rules: $handle.validate(),
104 });
105 },
106 render(children) {
107 if (children.length) {
108 children.push(this.makeFormBtn());
109 }
110 return this.$r(this.rule, isFalse(this.options.row.show) ? children : [this.makeRow(children)]);
111 },
112 makeWrap(ctx, children) {
113 const rule = ctx.prop;
114 const uni = `${this.key}${ctx.key}`;
115 const col = rule.col;
116 const isTitle = this.isTitle(rule);
117 const labelWidth = (!col.labelWidth && !isTitle) ? 0 : col.labelWidth;
118 const {inline, col: _col} = this.rule.props;
119 const item = isFalse(rule.wrap.show) ? children : this.$r(mergeProps([rule.wrap, {
120 props: {
121 labelWidth: labelWidth === void 0 ? labelWidth : toString(labelWidth),
122 ...(rule.wrap || {}),
123 prop: ctx.id,
124 rules: rule.validate,
125 },
126 class: rule.className,
127 key: `${uni}fi`,
128 ref: ctx.wrapRef,
129 type: 'formItem',
130 }]), [children, isTitle ? this.makeInfo(rule, uni) : null]);
131 return (inline === true || isFalse(_col) || isFalse(col.show)) ? item : this.makeCol(rule, uni, [item]);
132 },
133 isTitle(rule) {
134 if(this.options.form.title === false) return false;
135 const title = rule.title;
136 return !((!title.title && !title.native) || isFalse(title.show))
137 },
138 makeInfo(rule, uni) {
139 const titleProp = rule.title;
140 const infoProp = rule.info;
141 const isTip = isTooltip(infoProp);
142 const form = this.options.form;
143 const children = [titleProp.title + (form.labelSuffix || form['label-suffix'] || '')];
144 const titleFn = (pop) => this.$r(mergeProps([titleProp, {
145 props: titleProp,
146 slot: titleProp.slot || (pop ? (isTip ? 'default' : 'reference') : 'label'),
147 key: `${uni}tit`,
148 type: titleProp.type || 'span',
149 }]), children);
150
151 if (!isFalse(infoProp.show) && (infoProp.info || infoProp.native)) {
152 if (infoProp.icon !== false) {
153 children[infoProp.align !== 'left' ? 'unshift' : 'push'](this.$r({
154 type: 'i',
155 class: infoProp.icon === true ? 'el-icon-warning' : infoProp.icon,
156 key: `${uni}i`
157 }));
158 }
159 const prop = {
160 type: infoProp.type || 'popover',
161 props: {...infoProp},
162 key: `${uni}pop`,
163 slot: 'label'
164 };
165
166 const field = 'content';
167 if (infoProp.info && !hasProperty(prop.props, field)) {
168 prop.props[field] = infoProp.info;
169 }
170
171 return this.$r(mergeProps([infoProp, prop]), [
172 titleFn(true)
173 ])
174 }
175 return titleFn();
176 },
177 makeCol(rule, uni, children) {
178 const col = rule.col;
179 return this.$r({
180 class: col.class,
181 type: 'col',
182 props: col || {span: 24},
183 key: `${uni}col`
184 }, children);
185 },
186 makeRow(children) {
187 const row = this.options.row || {};
188 return this.$r({
189 type: 'row',
190 props: row,
191 class: row.class,
192 key: `${this.key}row`
193 }, children)
194 },
195 makeFormBtn() {
196 let vn = [];
197 if (!isFalse(this.options.submitBtn.show)) {
198 vn.push(this.makeSubmitBtn())
199 }
200 if (!isFalse(this.options.resetBtn.show)) {
201 vn.push(this.makeResetBtn())
202 }
203 if (!vn.length) {
204 return;
205 }
206 const item = this.$r({
207 type: 'formItem',
208 key: `${this.key}fb`
209 }, vn);
210
211 return this.rule.props.inline === true
212 ? item
213 : this.$r({
214 type: 'col',
215 props: {span: 24},
216 key: `${this.key}fc`
217 }, [item]);
218 },
219 makeResetBtn() {
220 const resetBtn = this.options.resetBtn;
221 return this.$r({
222 type: 'button',
223 props: resetBtn,
224 style: {width: resetBtn.width},
225 on: {
226 click: () => {
227 const fApi = this.$handle.api;
228 resetBtn.click
229 ? resetBtn.click(fApi)
230 : fApi.resetFields();
231 }
232 },
233 key: `${this.key}b2`,
234 }, [resetBtn.innerText]);
235 },
236 makeSubmitBtn() {
237 const submitBtn = this.options.submitBtn;
238
239 return this.$r({
240 type: 'button',
241 props: submitBtn,
242 style: {width: submitBtn.width},
243 on: {
244 click: () => {
245 const fApi = this.$handle.api;
246 submitBtn.click
247 ? submitBtn.click(fApi)
248 : fApi.submit();
249 }
250 },
251 key: `${this.key}b1`,
252 }, [submitBtn.innerText]);
253 }
254}