1. 效果演示

子表单添加、删除行时,计算单行结果和累计结果:
点此在线运行代码:https://jsbin.com/wofozir/edit?html,output
test_calc.gif

2. 在线体验

表单JSON如下,复制下列JSON,在表单设计器(点此进入)中选择“导入JSON”即可看到效果:

  1. {
  2. "widgetList": [
  3. {
  4. "type": "grid",
  5. "category": "container",
  6. "icon": "grid",
  7. "cols": [
  8. {
  9. "type": "grid-col",
  10. "category": "container",
  11. "icon": "grid-col",
  12. "internal": true,
  13. "widgetList": [
  14. {
  15. "type": "static-text",
  16. "icon": "static-text",
  17. "formItemFlag": false,
  18. "options": {
  19. "name": "static-text55175",
  20. "columnWidth": "200px",
  21. "hidden": false,
  22. "textContent": "子表单、计算字段演示",
  23. "customClass": [],
  24. "onCreated": "",
  25. "onMounted": "",
  26. "label": "static-text"
  27. },
  28. "displayName": "静态文字",
  29. "id": "static-text55175"
  30. }
  31. ],
  32. "options": {
  33. "name": "gridCol114213",
  34. "hidden": false,
  35. "span": 12
  36. },
  37. "id": "grid-col-114213"
  38. },
  39. {
  40. "type": "grid-col",
  41. "category": "container",
  42. "icon": "grid-col",
  43. "internal": true,
  44. "widgetList": [],
  45. "options": {
  46. "name": "gridCol80092",
  47. "hidden": false,
  48. "span": 12
  49. },
  50. "id": "grid-col-80092"
  51. }
  52. ],
  53. "options": {
  54. "name": "grid115477",
  55. "hidden": false,
  56. "gutter": 12,
  57. "customClass": []
  58. },
  59. "displayName": "栅格",
  60. "id": "grid115477"
  61. },
  62. {
  63. "type": "sub-form",
  64. "category": "container",
  65. "icon": "sub-form",
  66. "widgetList": [
  67. {
  68. "type": "input",
  69. "icon": "text-field",
  70. "formItemFlag": true,
  71. "options": {
  72. "name": "pName",
  73. "label": "产品名称",
  74. "type": "text",
  75. "defaultValue": "",
  76. "placeholder": "",
  77. "columnWidth": "150px",
  78. "size": "",
  79. "labelWidth": null,
  80. "labelHidden": false,
  81. "readonly": false,
  82. "disabled": false,
  83. "hidden": false,
  84. "clearable": true,
  85. "showPassword": false,
  86. "required": false,
  87. "validation": "",
  88. "validationHint": "",
  89. "customClass": [],
  90. "labelIconClass": null,
  91. "labelIconPosition": "rear",
  92. "labelTooltip": null,
  93. "minLength": null,
  94. "maxLength": null,
  95. "showWordLimit": false,
  96. "prefixIcon": "",
  97. "suffixIcon": "",
  98. "appendButton": false,
  99. "buttonDisabled": false,
  100. "buttonIcon": "el-icon-search",
  101. "onCreated": "",
  102. "onMounted": "",
  103. "onChange": "",
  104. "onValidate": ""
  105. },
  106. "displayName": "Input",
  107. "id": "input65393"
  108. },
  109. {
  110. "type": "number",
  111. "icon": "number-field",
  112. "formItemFlag": true,
  113. "options": {
  114. "name": "pNum",
  115. "label": "数量",
  116. "defaultValue": "1",
  117. "placeholder": "",
  118. "columnWidth": "200px",
  119. "size": "",
  120. "labelWidth": null,
  121. "labelHidden": false,
  122. "readonly": false,
  123. "disabled": false,
  124. "hidden": false,
  125. "required": false,
  126. "validation": "",
  127. "validationHint": "",
  128. "customClass": [],
  129. "labelIconClass": null,
  130. "labelIconPosition": "rear",
  131. "labelTooltip": null,
  132. "min": 0,
  133. "max": 100,
  134. "precision": 0,
  135. "step": 1,
  136. "controlsPosition": "right",
  137. "onCreated": "",
  138. "onMounted": "",
  139. "onChange": "recalcRowAmount(this, rowId)",
  140. "onValidate": ""
  141. },
  142. "displayName": "Number",
  143. "id": "number81340"
  144. },
  145. {
  146. "type": "number",
  147. "icon": "number-field",
  148. "formItemFlag": true,
  149. "options": {
  150. "name": "pPrice",
  151. "label": "单价",
  152. "defaultValue": "100",
  153. "placeholder": "",
  154. "columnWidth": "200px",
  155. "size": "",
  156. "labelWidth": null,
  157. "labelHidden": false,
  158. "readonly": false,
  159. "disabled": false,
  160. "hidden": false,
  161. "required": false,
  162. "validation": "",
  163. "validationHint": "",
  164. "customClass": [],
  165. "labelIconClass": null,
  166. "labelIconPosition": "rear",
  167. "labelTooltip": null,
  168. "min": 0,
  169. "max": 10000,
  170. "precision": 2,
  171. "step": 1,
  172. "controlsPosition": "right",
  173. "onCreated": "",
  174. "onMounted": "",
  175. "onChange": "recalcRowAmount(this, rowId)\n",
  176. "onValidate": ""
  177. },
  178. "displayName": "Number",
  179. "id": "number114595"
  180. },
  181. {
  182. "type": "number",
  183. "icon": "number-field",
  184. "formItemFlag": true,
  185. "options": {
  186. "name": "pAmount",
  187. "label": "小计金额",
  188. "defaultValue": 0,
  189. "placeholder": "",
  190. "columnWidth": "200px",
  191. "size": "",
  192. "labelWidth": null,
  193. "labelHidden": false,
  194. "readonly": true,
  195. "disabled": true,
  196. "hidden": false,
  197. "required": false,
  198. "validation": "",
  199. "validationHint": "",
  200. "customClass": [],
  201. "labelIconClass": null,
  202. "labelIconPosition": "rear",
  203. "labelTooltip": null,
  204. "min": 0,
  205. "max": 1000000,
  206. "precision": 2,
  207. "step": 1,
  208. "controlsPosition": "right",
  209. "onCreated": "",
  210. "onMounted": "",
  211. "onChange": "let taRef = this.getWidgetRef('totalAmount')\nrecalcSubFormTotal(subFormData, 'pAmount', taRef)\n",
  212. "onValidate": ""
  213. },
  214. "displayName": "Number",
  215. "id": "number35019"
  216. }
  217. ],
  218. "options": {
  219. "name": "sub-form7238",
  220. "showBlankRow": true,
  221. "showRowNumber": true,
  222. "labelAlign": "label-center-align",
  223. "hidden": false,
  224. "customClass": [],
  225. "onSubFormRowChange": "let taRef = this.getWidgetRef('totalAmount')\nrecalcSubFormTotal(subFormData, 'pAmount', taRef)\n",
  226. "onSubFormRowDelete": "",
  227. "onSubFormRowAdd": "",
  228. "onSubFormRowInsert": ""
  229. },
  230. "displayName": "SubForm",
  231. "id": "sub-form7238"
  232. },
  233. {
  234. "type": "grid",
  235. "category": "container",
  236. "icon": "grid",
  237. "cols": [
  238. {
  239. "type": "grid-col",
  240. "category": "container",
  241. "icon": "grid-col",
  242. "internal": true,
  243. "widgetList": [
  244. {
  245. "type": "input",
  246. "icon": "text-field",
  247. "formItemFlag": true,
  248. "options": {
  249. "name": "totalAmount",
  250. "label": "总计金额",
  251. "type": "text",
  252. "defaultValue": "",
  253. "placeholder": "",
  254. "columnWidth": "200px",
  255. "size": "",
  256. "labelWidth": null,
  257. "labelHidden": false,
  258. "readonly": true,
  259. "disabled": true,
  260. "hidden": false,
  261. "clearable": true,
  262. "showPassword": false,
  263. "required": false,
  264. "validation": "",
  265. "validationHint": "",
  266. "customClass": [],
  267. "labelIconClass": null,
  268. "labelIconPosition": "rear",
  269. "labelTooltip": null,
  270. "minLength": null,
  271. "maxLength": null,
  272. "showWordLimit": false,
  273. "prefixIcon": "",
  274. "suffixIcon": "",
  275. "appendButton": false,
  276. "buttonDisabled": false,
  277. "buttonIcon": "el-icon-search",
  278. "onCreated": "",
  279. "onMounted": "",
  280. "onChange": "",
  281. "onValidate": ""
  282. },
  283. "displayName": "Input",
  284. "id": "input55898"
  285. }
  286. ],
  287. "options": {
  288. "name": "gridCol33828",
  289. "hidden": false,
  290. "span": 12
  291. },
  292. "id": "grid-col-33828"
  293. },
  294. {
  295. "type": "grid-col",
  296. "category": "container",
  297. "icon": "grid-col",
  298. "internal": true,
  299. "widgetList": [
  300. {
  301. "type": "input",
  302. "icon": "text-field",
  303. "formItemFlag": true,
  304. "options": {
  305. "name": "totalCount",
  306. "label": "total count",
  307. "type": "text",
  308. "defaultValue": "",
  309. "placeholder": "",
  310. "columnWidth": "200px",
  311. "size": "",
  312. "labelWidth": null,
  313. "labelHidden": false,
  314. "readonly": true,
  315. "disabled": false,
  316. "hidden": true,
  317. "clearable": true,
  318. "showPassword": false,
  319. "required": false,
  320. "validation": "",
  321. "validationHint": "",
  322. "customClass": [],
  323. "labelIconClass": null,
  324. "labelIconPosition": "rear",
  325. "labelTooltip": null,
  326. "minLength": null,
  327. "maxLength": null,
  328. "showWordLimit": false,
  329. "prefixIcon": "",
  330. "suffixIcon": "",
  331. "appendButton": false,
  332. "buttonDisabled": false,
  333. "buttonIcon": "el-icon-search",
  334. "onCreated": "",
  335. "onMounted": "",
  336. "onChange": "",
  337. "onValidate": ""
  338. },
  339. "displayName": "Input",
  340. "id": "input77431"
  341. }
  342. ],
  343. "options": {
  344. "name": "gridCol69043",
  345. "hidden": false,
  346. "span": 12,
  347. "customClass": []
  348. },
  349. "id": "grid-col-69043"
  350. }
  351. ],
  352. "options": {
  353. "name": "grid55046",
  354. "hidden": false,
  355. "gutter": 12,
  356. "customClass": []
  357. },
  358. "displayName": "Grid",
  359. "id": "grid55046"
  360. }
  361. ],
  362. "formConfig": {
  363. "labelWidth": 80,
  364. "labelPosition": "left",
  365. "size": "",
  366. "labelAlign": "label-left-align",
  367. "cssCode": "",
  368. "customClass": [],
  369. "functions": "function myAlert(msg) {\n alert(msg)\n}\n\nfunction recalcRowAmount(changeObj, rowId) {\n let numR = changeObj.getWidgetRef('pNum' + '@row' + rowId)\n let priceR = changeObj.getWidgetRef('pPrice' + '@row' + rowId)\n let amountR = changeObj.getWidgetRef('pAmount' + '@row' + rowId)\n let amountMoney = numR.getValue() * 1 * priceR.getValue()\n amountR.setValue(amountMoney)\n}\n\nfunction recalcSubFormTotal(subFormData, rowFieldName, totalFieldRef) {\n let tc = 0\n if (!!subFormData && (subFormData.length > 0)) {\n subFormData.forEach(function(row) {\n tc += row[rowFieldName] * 1\n })\n }\n totalFieldRef.setValue(tc)\n}\n",
  370. "layoutType": "PC",
  371. "onFormCreated": "",
  372. "onFormMounted": "",
  373. "onFormDataChange": "",
  374. "onFormValidate": ""
  375. }
  376. }

3. 实现思路解说

计算字段实现方法:
(1) 在表单全局函数中定义单行计算函数recalcRowAmount、累计计算函数recalcSubFormTotal;
image.png
image.png
(2)在数量、单价字段的onChange事件中调用recalcRowAmount进行单行计算;
(3)在小计金额字段的onChange事件中调用recalcSubFormTotal进行累计计算;
(4)为了在子表单删除、新增行后也能重新计算累计金额,需要在子表单的onSubFormRowChange事件中调用recalcSubFormTotal进行累计计算。注:子表单的onSubFormRowChange事件在新增行、插入行、删除行时被触发。
image.png
(5)通过以上步骤,子表单的单行计算、累计计算已实现。