IMPORTANT NOTE: Correction of Price value on form_Order
After posting this “Part-2 , Database-Insert”, I got a message from @Ben pointing out that there is a possibility of hacking values (especially the price one) that can be changed because the inputs from the datastore are not to be trusted and can easily be changed by a skilled person.
THANKS @BEN FOR YOUR VALUABLE ADVICE!!So, I apologize and in order to fix this “open door” we will just pull all of the Price Inputs of the frm_Order DIRECTLY from the database and not from the DataStore
Please scroll down to to the bottom of this post to see the changes:
Hey guys,
On the first Part, we created a Shopping Cart with the DataSore component and saw the manipulation of a Data Store containing Array Field using an alternative-temporary Data Store for the Array fields.
The Part-1 is here: Showcase: DataStore, Manipulating Array fields inside DataStore (Client_side)
Now in Part-2 we will continue from where we left off…
We have our Data Store filled with our Order’s products and their Variations, ready to be submitted.
Main DataStore “yourCart”:
{
"$type": "datastore",
"data": [
{
"$id": 7,
"prd_id": 9,
"prd_qnt": 1,
"prd_prc": "23.00",
"prd_name": "TShirt-3",
"prod_vars": [
{
"$id": 1,
"var_id": 3,
"var_name": "Color",
"var_val_id": "14",
"var_val_name": "Black",
"var_val_prc": 1
}
]
},
{
"$id": 8,
"prd_id": 9,
"prd_qnt": 1,
"prd_prc": "23.00",
"prd_name": "TShirt-3"
},
{
"$id": 9,
"prd_id": 2,
"prd_qnt": 1,
"prd_prc": "165.00",
"prd_name": "Mobile-2",
"prod_vars": [
{
"$id": 1,
"var_id": 1,
"var_name": "RAM Memory",
"var_val_id": 41,
"var_val_name": "64GB",
"var_val_prc": 18
},
{
"$id": 2,
"var_id": 4,
"var_name": "Color",
"var_val_id": "16",
"var_val_name": "White",
"var_val_prc": 1
}
]
}
]
}
At this point we have to solve a problem…
The DataStore contains all the information/data we need but we must find a way to transform/translate their structure in a form and submit them in server to complete the desired Database Insert.
Here is our Orders table schema:
Our Insert must have this Payload:
ord_usr_id: 1
ord_date: 2023-08-07
formRepeatProducts[0][ord_product_id]: 9
formRepeatProducts[0][ord_prd_quantity]: 1
formRepeatProducts[0][ord_prd_price]: 23.00
formRepeatProducts[0][formRepeatVariations][0][ord_prd_var_Var_id]: 3
formRepeatProducts[0][formRepeatVariations][0][ord_prd_var_Val_id]: 14
formRepeatProducts[0][formRepeatVariations][0][ord_prd_var_Val_exprice]: 1.00
formRepeatProducts[1][ord_product_id]: 9
formRepeatProducts[1][ord_prd_quantity]: 1
formRepeatProducts[1][ord_prd_price]: 23.00
formRepeatProducts[2][ord_product_id]: 2
formRepeatProducts[2][ord_prd_quantity]: 1
formRepeatProducts[2][ord_prd_price]: 165.00
formRepeatProducts[2][formRepeatVariations][0][ord_prd_var_Var_id]: 1
formRepeatProducts[2][formRepeatVariations][0][ord_prd_var_Val_id]: 63
formRepeatProducts[2][formRepeatVariations][0][ord_prd_var_Val_exprice]: 18.00
formRepeatProducts[2][formRepeatVariations][1][ord_prd_var_Var_id]: 4
formRepeatProducts[2][formRepeatVariations][1][ord_prd_var_Val_id]: 16
formRepeatProducts[2][formRepeatVariations][1][ord_prd_var_Val_exprice]: 1.00
This payload needs this POST structure in our “order_add” Server Action.
So, we create one more modal(Modal_Checkout) to keep the data from our DataStore and insert a form in it once the “CheckOut” is clicked.
Here is the final layout of the Modal_Checkout:
And here is the code of the form “frm_Order” holding the data to be sumbmitted:
<form id="frm_Order" is="dmx-serverconnect-form" method="post" action="dmxConnect/api/orders/order_add.php" dmx-on:success="notifies1.success('Order successfully sent...');frm_Order.reset(true);modal_Checkout.hide();yourCart.clear()">
<div class="row g-0">
<div class="col-12 bg-secondary bg-opacity-50 text-white pt-3 ps-2 pe-2">
<div class="form-group mb-3 row">
<label for="ord_usr_id" class="col-sm-2 col-form-label text-sm-end pe-0 fw-bold">Client :</label>
<div class="col-sm-10">
<input class="form-control" id="ord_usr_id" name="ord_usr_id" placeholder="Client" dmx-bind:value="srvc_ProdList.data.qr_userLoggedIn.usr_id" type="hidden">
<p class="rounded text-primary bg-white fw-bold mb-0 pt-1 pb-1 ps-3 pe-2 lh-lg" dmx-text="srvc_ProdList.data.qr_userLoggedIn.usr_fname+' '+srvc_ProdList.data.qr_userLoggedIn.usr_lname+' ('+srvc_ProdList.data.qr_userLoggedIn.usr_username+')'">Fancy display heading</p>
</div>
</div>
<div class="form-group mb-3 row">
<label for="ord_date" class="col-sm-2 col-form-label text-sm-end pe-0 fw-bold">Date :</label>
<div class="col-sm-10">
<input type="text" class="form-control text-primary fw-bold bg-white" id="ord_date" name="ord_date" placeholder="Client" is="dmx-date-picker" dmx-bind:customdates="srvc_ProdList.data.serverTime" customdates-start="srvc_ProdList.data.serverTime" customdates-end="srvc_ProdList.data.serverTime" dmx-bind:value="srvc_ProdList.data.serverTime">
</div>
</div>
</div>
</div>
<div class="row g-0 pt-2 fw-bold small" style="/* min-width: 760px */ /* overflow-x: auto */ white-space: nowrap;">
<h5 class="ps-2">Your Products:</h5>
<section class="row g-0 px-1 align-items-center py-1 border-bottom border-secondary">
<div class="pe-1 small text-center align-self-end col-4">
<p class="mb-0">Product</p>
</div>
<div class="pe-1 small text-center col-sm-1 col-2 align-self-end">
<p class="mb-0 text-center">Quantity</p>
</div>
<div class="pe-1 small text-center col-2 align-self-end">
<p class="mb-0">Price</p>
</div>
<div class="pe-1 small text-center col-sm-1 align-self-end col-3">
<p class="mb-0">Amount</p>
</div>
<div class="bg-light d-none d-sm-block col-sm-4">
<div class="row g-0">
<p class="small text-center lh-sm mb-0 border-bottom">Variations</p>
</div>
<div class="row g-0 align-items-center">
<div class="col-5 ps-1 pe-0 small text-center">
<p class="mb-0 lh-1">Variation</p>
</div>
<div class="col-4 ps-1 pe-0 text-center small">
<p class="mb-0 lh-1">Value</p>
</div>
<div class="col-3 ps-1 pe-0 text-center small">
<p class="mb-0 lh-1">Price</p>
</div>
</div>
</div>
</section>
<div id="formRepeatProducts" is="dmx-repeat" dmx-bind:repeat="yourCart.data">
<div class="row g-0 align-items-center border-bottom border-dark">
<dmx-value id="prod_index" dmx-bind:value="$index"></dmx-value>
<div class="pe-1 align-self-center col-4">
<input id="ord_product_id" dmx-bind:name="'formRepeatProducts['+$index+'][ord_product_id]'" type="hidden" class="form-control bg-white" readonly="true" dmx-bind:value="prd_id.toNumber()">
<legend dmx-text="prd_name" class="col-form-label-sm mb-0 ps-1">Product</legend>
</div>
<div class="pe-1 col-sm-1 col-2 text-sm-center">
<input id="ord_prd_quantity" dmx-bind:name="'formRepeatProducts['+$index+'][ord_prd_quantity]'" type="number" class="form-control bg-white border-0 form-control-sm text-center" readonly="true" dmx-bind:value="prd_qnt">
</div>
<div class="pe-1 col-2">
<dmx-serverconnect id="srvc_GetProductPrice" url="dmxConnect/api/products/prod_readProductPrice.php" dmx-param:prid="ord_product_id.value"></dmx-serverconnect>
<input id="ord_prd_price" dmx-bind:name="'formRepeatProducts['+$index+'][ord_prd_price]'" type="number" class="form-control bg-white border-0 form-control-sm text-end" readonly="true" dmx-bind:value="srvc_GetProductPrice.data.qr_GetProductPrice.prd_price">
</div>
<div class="pe-1 col-sm-1 text-end col-3">
<legend dmx-text="(prd_qnt*ord_prd_price.value).toFixed(2)" class="col-form-label-sm mb-0 w-100">Amount</legend>
</div>
<div class="col-3 px-0 d-none d-sm-block col-sm-4">
<div id="formRepeatVariations" is="dmx-repeat" dmx-bind:repeat="prod_vars">
<div class="row g-0 p-0 rounded rounded-1 bg-light border-info border-bottom">
<div class="col-5 ps-1 pe-0 align-self-center fw-normal">
<input id="ord_prd_var_Var_id" dmx-bind:name="'formRepeatProducts['+prod_index.value+'][formRepeatVariations]['+$index+'][ord_prd_var_Var_id]'" type="hidden" class="form-control bg-transparent form-control-sm text-center" readonly="true" dmx-bind:value="var_id">
<legend dmx-text="var_name" class="col-form-label-sm mb-0 text-primary w-100 text-center lh-1">Var</legend>
</div>
<div class="col-4 ps-1 pe-0 align-self-center fw-normal">
<input id="ord_prd_var_Val_id" class="form-control bg-transparent text-primary form-control-sm text-center" readonly="true" type="hidden" dmx-bind:name="'formRepeatProducts['+prod_index.value+'][formRepeatVariations]['+$index+'][ord_prd_var_Val_id]'" dmx-bind:value="var_val_id">
<legend dmx-text="var_val_name" class="col-form-label-sm mb-0 text-primary w-100 text-center lh-1">Var</legend>
</div>
<div class="col-3 px-1 py-0 lh-1">
<input id="ord_prd_var_Val_exprice" class="form-control bg-transparent border-0 text-end form-control py-0" readonly="true" type="number" dmx-bind:name="'formRepeatProducts['+prod_index.value+'][formRepeatVariations]['+$index+'][ord_prd_var_Val_exprice]'" dmx-bind:value="var_val_prc.toNumber().toFixed(2)">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
So, now we have our form set let’s view our Sercer Action “order_add”…
-
We add a Database Insert step inserting only the main 2 fields:
-
We add a Repeat step based on $_POST.formRepeatProducts:
-
We add a Database Insert step inserting only the 1st level Subtable’s fields and the 2nd level Subtable:
Back to our page to submit and check the results.
So, now by clicking the “Send Order” button we submit the order.
Let’s confirm that the data were inserted correctly:
And we are done with the Insert…
I’m working on the Update trying to solve a few problems and go for Part-3 / Database Update.
Any correction, instruction or advice will be much appreciated!!
For those who don’t really understand something from this small demo please “ring the bell” for explanations.
Thanks Wappler Community, thanks Wappler Team!
**
CHANGES MADE:
Here is the code for the Price and Amount Input in our form BEFORE the correction:
Here is the (small) changes that @Ben proposed and we have to make:
We create a ServerConnect “prod_readProductPrice” and add a single record query in it with a condition driven by a GET parameter “prid” (get the product with product_id=prid)
We place the ServerConnect “prod_readProductPrice” inside the “formRepeatProducts” and assign as a prid parameter the current DataStore product_id in order to pull the database product details.
We change the Price input value to dmx-bind:value=“srvc_GetProductPrice.data.qr_GetProductPrice.prd_price”:
We should change also the Amount value to match the multiple of quantity*price :
My apologies for this open door, the only reason that happened is because my project is going to be used only by autherized users with granted permissions to register client’s orders. There is no excuse, I am sorry for this.
And thanks to Ben one more time for everything!