Showcase: DataStore, Manipulating Array fields inside DataStore (Client_side)

Hey guys,

I was searching for a while how to set and restore the data from a DataStore when it contains field of type Array.
I decided to do a small demo for this case…

In this demo I will show how to handle product Variations inside a Cart/Order.
I created a Cart. I haven’t changed or do something different from what we have seen in these two tutorials from Teodor for Insert and Update Main/Subtable data procedures:

(I just created a Variation page so I can Insert/Update my product Variations in order to demonstrate the procedure)

I will use a main DataStore component to hold my products for final submitting to server and a temporary Datastore component (with the same schema as the main’s array field) to handle temporarily each product Variations.
Main DataStore = yourCart
Temporary DataStore = prod_vars

**Note: Because my project required to optionally add or no variations to each product in Cart, I have left just for that demo the ability to add to Cart products without variations set, so Variations are optional.

Here is the Product Page:

The “Add to Cart” button…
I always perform ONLY DataStore.Insert (and not Upsert) because the same product(id) can be added more than one time with different Variations:

<a href="javascript:void(0)" class="btn border-0 rounded-pill btn-outline-light lh-1 btn-lg" dmx-on:click="run({condition:{if:`yourCart.data.values(\`prd_id\`).contains(prd_id)`,then:{steps:{'bootbox.confirm':{title:'Product already in Cart...',message:'This product is already in Cart... Do you want to add it in a new line?',buttons:{confirm:{label:'Add New',className:'btn-danger'},cancel:{label:'Cancel',className:'btn-secondary'}},swapButtonOrder:true,then:{steps:[{run:{action:`yourCart.insert({prd_id: prd_id, prd_qnt: 1, prd_prc: prd_price, prd_name: prd_name})`,outputType:'text'}},{run:{action:`notifies1.success(\'Product added to Cart...\')`,outputType:'text'}}]},name:'ProductExists'}}},else:{steps:[{run:{action:`yourCart.insert({prd_id: prd_id, prd_qnt: 1, prd_prc: prd_price, prd_name: prd_name})`,outputType:'text'}},{run:{action:`notifies1.success(\'Product added to Cart...\')`,outputType:'text'}}]},outputType:'boolean'}})">Add to Cart</a>

We “Add to Cart” a product:

And check our Cart:

So, if I click again “Add to Cart” the same product, before the same product is “Added to Cart” an alert pops-up and ask for a Confirmation:

I click on “Add New” and check our Cart that we see 2 entries (lines) of the same product:

I click on the “OpenVariations” button of the first product(line) to update its Variations:

Now, let’s see what is the click Event Flow for the “OpenVariations” button…
I assign values to some necessary inputs and load a VariationList action filtered by the Category of the selected product. Then if the Main DataStore’ entry of that product has already Variations set , we copy them into the Temporary DataStore:

<button id="btn_OpenVariations" class="btn btn-sm lh-1 px-1 btn-outline-dark" data-bs-target="#modal_LineVariations" dmx-on:click="run([{run:{action:`modal_LineVariations.prd_indx.setValue($index);modal_LineVariations.prdid.setValue($id);prodVars.clear()`,outputType:'text'}},{run:{action:`data_detailProductLine.select(prd_id)`,outputType:'text'}},{run:{action:`srvc_VariationList.load({catid: data_detailProductLine.data.prd_cat, used_vars: prodVars.data})`,outputType:'text'}},{assign:{value:`$index`,name:'prod_id',outputType:'text'}},{condition:{if:`yourCart.data[prod_id.toNumber()].prod_vars.count()&gt;0`,then:{steps:{repeat:{repeat:`prod_vars`,outputFields:['var_id','var_name','var_val_id','var_val_name','var_val_prc'],exec:{steps:{run:{action:`prodVars.insert({var_id: prod_vars[$index].var_id.toNumber() , var_name: prod_vars[$index].var_name, var_val_id: prod_vars[$index].var_val_id.toNumber(), var_val_name: prod_vars[$index].var_val_name, var_val_prc: prod_vars[$index].var_val_prc.toNumber()})`,outputType:'text'}}},name:'repeat',output:true,outputType:'array'}}},outputType:'boolean'}}])">
    <i class="fas fa-sliders-h fa-lg"></i>
</button>

***EDIT: IMPORTANT STEP, At this point you must enter by hand the output fields of the repeat (check image below)

So, by clicking the “btn_OpenVariations” button the “Product Variations” Modal opens:


a) I click the “Add Variation” button that opens the “Viriation Details” Collapse and select the Variation I want (left) and its Value (rifgt), if i want I can overide its default Price for this Variation’s Value

NOTE: The Variations are defined based on Product Category) available for this product

b) After selecting the Variation and Value that I want I click the “Save Details” button in order to save the Variation in the Temporary DataStore:


Now, let’s see what is the click Event Flow for the “Save Details” button…
I check if the Variation exists in the Temporary DataStore (prodVars_id.value.toNumber()>0), if it exists the DataSore.Update else DataStore.Insert

<button id="btn_SaveVarUpsert" class="btn btn-primary w-100 shadow" dmx-on:click="run([{condition:{if:`prodVars_id.value.toNumber()&gt;0`,then:{steps:{run:{action:`prodVars.update({$id: prodVars_id.value.toNumber()},{var_id: selectVar.selectedValue.toNumber(), var_name: selectVar.selectedText, var_val_id: selectVarValue.selectedValue, var_val_name: selectVarValue.selectedText, var_val_prc: inp_VarOptionPrice.value.toNumber()})`,outputType:'text'}}},else:{steps:{run:{action:`prodVars.insert({var_id: selectVar.selectedValue.toNumber(), var_name: selectVar.selectedText, var_val_id: selectVarValue.selectedValue, var_val_name: selectVarValue.selectedText, var_val_prc: inp_VarOptionPrice.value.toNumber()})`,outputType:'text'}}},outputType:'boolean'}},{run:{action:`collapseVariation.hide()`,outputType:'text'}}])" dmx-bind:disabled="!selectVar.value||!selectVarValue.value">Save Details</button>

So, after “Save Details” button is clicked, the Details List is updated
(STILL WORKING ON THE TEMPORARY DATASTORE)

And when we are done with the Variations for that product we click the “Save Changes” button…

What “Save Changes” button does?
Performs a Main DataStore.Update based on $id BUT no field is assigned in the UI. We just code by hand assigning the whole Temporary Datastore into “prod_vars” Array field of the Main DataStore

<button class="btn btn-primary btn-lg w-100" dmx-on:click="yourCart.update({$id: prdid.value.toNumber()},{prod_vars: prodVars.data});modal_LineVariations.hide();modal_Cart.toggle()" dmx-bind:disabled="!collapseVariation.collapsed">Save changes</button

And here we are back at our store updated with the Variation for the specific product.
(NOW DATA COME FROM THE MAIN DATASTORE HERE)

So, now lets quickly add to Cart a Mobile-2 product and assign two variations for it:










And at this stage I suppose you got the point…

Now we have our Main DataStore “yourCart” data packed ready to go:

{
    "$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
                }
            ]
        }
    ]
}

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!

3 Likes