@@ -4750,6 +4750,221 @@ describe('Process Tests', function () {
47504750 assert . deepEqual ( context . scope . errors . length , 0 ) ;
47514751 } ) ;
47524752
4753+ it ( 'Should calculate value on server for calculations based on dataSource component' , async function ( ) {
4754+ const form = {
4755+ _id : '6752ad48eda1569ebc9aaead' ,
4756+ title : 'cart' ,
4757+ name : 'Cart' ,
4758+ path : '9357cart' ,
4759+ type : 'form' ,
4760+ display : 'form' ,
4761+ components : [
4762+ {
4763+ label : 'Products' ,
4764+ persistent : 'client-only' ,
4765+ trigger : {
4766+ init : true ,
4767+ server : true
4768+ } ,
4769+ dataSrc : 'url' ,
4770+ fetch : {
4771+ url : '{{ config.appUrl }}/product/submission' ,
4772+ method : 'get' ,
4773+ headers : [
4774+ {
4775+ key : '' ,
4776+ value : ''
4777+ }
4778+ ] ,
4779+ mapFunction : '' ,
4780+ forwardHeaders : false ,
4781+ } ,
4782+ allowCaching : true ,
4783+ key : 'products' ,
4784+ type : 'datasource' ,
4785+ input : true ,
4786+ tableView : false
4787+ } ,
4788+ {
4789+ label : 'Cart' ,
4790+ reorder : false ,
4791+ addAnotherPosition : 'bottom' ,
4792+ layoutFixed : false ,
4793+ enableRowGroups : false ,
4794+ initEmpty : false ,
4795+ tableView : false ,
4796+ key : 'cart' ,
4797+ type : 'datagrid' ,
4798+ input : true ,
4799+ components : [
4800+ {
4801+ label : 'Product' ,
4802+ widget : 'choicesjs' ,
4803+ tableView : true ,
4804+ dataSrc : 'custom' ,
4805+ data : {
4806+ custom : 'values = data.products;'
4807+ } ,
4808+ valueProperty : '_id' ,
4809+ template : '\u003Cspan\u003E{{ item.data.name }}\u003C/span\u003E' ,
4810+ refreshOn : 'products' ,
4811+ key : 'product' ,
4812+ type : 'select' ,
4813+ input : true
4814+ } ,
4815+ {
4816+ label : 'Quantity' ,
4817+ applyMaskOn : 'change' ,
4818+ mask : false ,
4819+ tableView : false ,
4820+ delimiter : false ,
4821+ requireDecimal : false ,
4822+ inputFormat : 'plain' ,
4823+ truncateMultipleSpaces : false ,
4824+ key : 'quantity' ,
4825+ type : 'number' ,
4826+ input : true ,
4827+ defaultValue : 1
4828+ } ,
4829+ {
4830+ label : 'Price' ,
4831+ applyMaskOn : 'change' ,
4832+ mask : false ,
4833+ tableView : false ,
4834+ delimiter : false ,
4835+ requireDecimal : false ,
4836+ inputFormat : 'plain' ,
4837+ truncateMultipleSpaces : false ,
4838+ redrawOn : 'cart.product' ,
4839+ calculateValue : 'var productId = row.product;\nvalue = 0;\nif (productId && data.products && data.products.length) {\n data.products.forEach(function(product) {\n if (product._id === productId) {\n value = product.data.price * (row.quantity || 1);\n }\n });\n}' ,
4840+ calculateServer : true ,
4841+ key : 'price' ,
4842+ type : 'number' ,
4843+ input : true
4844+ }
4845+ ]
4846+ } ,
4847+ {
4848+ label : 'Total' ,
4849+ applyMaskOn : 'change' ,
4850+ mask : false ,
4851+ tableView : false ,
4852+ delimiter : false ,
4853+ requireDecimal : false ,
4854+ inputFormat : 'plain' ,
4855+ truncateMultipleSpaces : false ,
4856+ redrawOn : 'cart' ,
4857+ calculateValue : 'if (data.cart && data.cart.length) {\n value = data.cart.reduce(function(total, cartItem) {\n return total + cartItem.price;\n }, 0);\n}' ,
4858+ calculateServer : true ,
4859+ key : 'total' ,
4860+ type : 'number' ,
4861+ input : true
4862+ } ,
4863+ {
4864+ type : 'button' ,
4865+ label : 'Submit' ,
4866+ key : 'submit' ,
4867+ disableOnInvalid : true ,
4868+ input : true ,
4869+ tableView : false
4870+ }
4871+ ] ,
4872+ created : '2024-12-06T07:52:40.891Z' ,
4873+ modified : '2024-12-06T08:33:40.971Z' ,
4874+ config : {
4875+ appUrl : 'http://localhost:3000/idwqwhclwioyqbw'
4876+ } ,
4877+ } ;
4878+
4879+ const resource = [
4880+ {
4881+ _id : '6752adf3eda1569ebc9ab0cd' ,
4882+ data : {
4883+ name : 'Cream' ,
4884+ price : 30
4885+ } ,
4886+ } ,
4887+ {
4888+ _id : '6752adf4eda1569ebc9ab0df' ,
4889+ data : {
4890+ name : 'Perfume' ,
4891+ price : 100
4892+ } ,
4893+ } ,
4894+ {
4895+ _id : '6752adf4eda1569ebc9ab0f1' ,
4896+ data : {
4897+ name : 'Soap' ,
4898+ price : 5
4899+ } ,
4900+ } ,
4901+ {
4902+ _id : '6752adf4eda1569ebc9ab103' ,
4903+ data : {
4904+ name : 'Toothpaste' ,
4905+ price : 10
4906+ } ,
4907+ } ,
4908+ {
4909+ _id : '6752adf4eda1569ebc9ab115' ,
4910+ data : {
4911+ name : 'Shampoo' ,
4912+ price : 20
4913+ } ,
4914+ }
4915+ ] ;
4916+
4917+ const submission = {
4918+ data : {
4919+ cart : [
4920+ {
4921+ product : '6752adf4eda1569ebc9ab115' ,
4922+ quantity : 5 ,
4923+ price : 100
4924+ } ,
4925+ {
4926+ product : '6752adf4eda1569ebc9ab103' ,
4927+ quantity : 3 ,
4928+ price : 30
4929+ } ,
4930+ {
4931+ product : '6752adf4eda1569ebc9ab0df' ,
4932+ quantity : 2 ,
4933+ price : 200
4934+ }
4935+ ] ,
4936+ total : 330 ,
4937+ submit : true
4938+ } ,
4939+ state : 'submitted'
4940+ } ;
4941+
4942+ const context = {
4943+ form,
4944+ submission,
4945+ data : submission . data ,
4946+ components : form . components ,
4947+ processors : ProcessTargets . submission ,
4948+ scope : { } ,
4949+ fetch : ( ) : Promise < Response > => {
4950+ return Promise . resolve ( {
4951+ ok : true ,
4952+ json : ( ) => {
4953+ return Promise . resolve ( resource ) ;
4954+ }
4955+ } as Response ) ;
4956+ } ,
4957+ config : {
4958+ server : true ,
4959+ } ,
4960+ } ;
4961+ await process ( context ) ;
4962+ submission . data = context . data ;
4963+ context . processors = ProcessTargets . evaluator ;
4964+ await process ( context ) ;
4965+ assert . deepEqual ( context . data , submission . data ) ;
4966+ } ) ;
4967+
47534968 describe ( 'Required component validation in nested form in DataGrid/EditGrid' , function ( ) {
47544969 const nestedForm = {
47554970 key : 'form' ,
0 commit comments