+ Start a Discussion
Kent Lichty 11Kent Lichty 11 

How to return class wrapper values back to apex from LWC

My organization is in the process of implementing Salesforce as its ERP, just as I am in the process of learning Force.com programming.  I have been asked to develop a solution which I am just not sure is possible and, if it is, then it will require programming skills in LWC development that are currently beyond me.  So I would be very grateful if anyone in this forum could offer some assistance.

The root of the problem is that, when custom objects were developed, it was not understood that Salesforce works much better when custom objects are designed in a “denormalized” manner, where a single “long” record would contain many fields.  We were still thinking in “normalized” SQL terms, where narrower objects were created, linked by keys.  Here is a simple, if not realistic, example of what I am attempting to describe:

We have a custom “Product Price” object which contains these three fields:

Product, Currency Code, Price. 

So three records would look like this:
PRODUCT 1         USD       25.00
PRODUCT1          EUR        28.00
PRODUCT1          GBP       29.50

However, while the records are STORED in the above manner, it is realized that it is difficult and cumbersome to display/maintain the records using standard Salesforce functionality, so I have been asked to come up with a UI that would make it easier to enter/change the prices for each product, which would look something like this, in a datatable where the prices would be EDITABLE:

PRODUCT ID       USD PRICE           EUR PRICE           GBP PRICE                          
PRODUCT1          25.00                      28.00                     29.50
PRODUCT2          50.00                      54.00                     _____
PRODUCT3          75.00                       _____                   80.00

I am able to easily define and display a class wrapper which contains the information that I want to DISPLAY; that is no problem.  The issue with which I am struggling is the UPDATE part, especially given the fact that I have no valid record ID because in this case, THREE record IDs would be involved, one for each record in the Product Price object.  If I can get the list back to Apex (preferably only MODIFIED records in the list) back to Apex, then I would be good to go.  But that is the part that I am not understanding: how to get my modified datatable records back to Apex so I can process them.

I am guessing that what I want to do IS POSSIBLE, by doing something like this, but the exact details are not apparent to me:

1:  Add a button (Save/Update) that would call my Apex program imperatively, passing the list back to it. The button would fire a Javascript function which would do the following.

2:  Using the concept of draft values, the function would read the list and only pass back to Apex the records which had been modified.  But I have no clue how to do that.  I assume this would require sending back either JSON or a map <String, Object> back to my Apex controller. This is the critical part that I am not understanding.

3:  Once I get the list records back to Apex, I think I can handle the update part.  I would probably send the 3 record IDs of the Product Price as part of my class wrapper so I could use them to get a handle on any records that I need to update.

So that is my problem.  I am hoping that some other people have had the same issue and have been able to come up with a solution which currently eludes me.  If anybody could just tell me in general the techniques that I could use to implement my goal, I can do the research and figure out the details.  Also, if any could point me to any sites which describe a similar problem and solution, I would be exceedingly grateful.                
 
Abhishek BansalAbhishek Bansal
Hi Kent,

You can find the complete help on the link given below:
https://salesforcediaries.com/2020/01/18/wrapper-class-in-lightning-web-component/
https://www.salesforcecodecrack.com/2020/01/using-wrapper-class-in-lighting-web.html​​​​​​​ (https://www.salesforcecodecrack.com/2020/01/using-wrapper-class-in-lighting-web.html)

Let me know if you still have any doubts.

Thanks,
Abhishek Bansal.
Kent Lichty 11Kent Lichty 11
Abhishek, I truly appreciate your quick response to my question. However, I have already studied the same links that you sent back to me, which all describe how to retrieve a class wrapper from Apex and then display it in my LWC datatable. I already know how to do that. What I need to know is how to RETURN that modified list of the wrapper class BACK to my Apex program so I can process it. But thank you again for trying to help me.
Abhishek BansalAbhishek Bansal
Hi Kent,

Firts of all you need to import that method in your lwc and then you can use the below code snippet:
saveRecord(event ){

        updateMyContact({con : this.realFormData}).then(()=>{
                //do something here
        });

    }
where saveRecord can be called from a button like this:
<button  class="slds-button" onclick={saveRecord}> Save Record</button>
You can use your the wrapper list property in place of this.realFormData and con would be the name of the parameter defined in the method of the class.

Let me know if you still have any doubts.

Thanks,
Abhishek Bansal.
Kent Lichty 11Kent Lichty 11
Thank you so much Abhishek; this was exactly the kind of information that I was looking for. I will try out your suggestion and will hopefully be able to mark it as the best answer. Thanks again!
Kent Lichty 11Kent Lichty 11
I wanted to get back to you about this Abhishek, and please know how much I appreciate your help. I did not try to implement your proposed solution specifically (which I may still need to do), because if at all possible I want to use the standard datatable‘ Save’ draft values approach. I think I am VERY CLOSE to being able to achieve this, and I am sure that somebody in this forum who knows much more about LWC and JavaScript coding can help me get to the finish line. Again, my challenge is that I am presenting a list of a custom wrapper objects that combines elements of a Product sObject and a Price sObject. DISPLAYING the wrapper class is quite simple, but it is the UPDATE part of the process that is confounding me. There is just very little discussion about to UPDATE a class wrapper in Apex out there. For what it’s worth, here is my wrapper class which is keyed by a “product” code and then has the associated prices in 6 different currencies, along with some other information about the product. *public String product{get;set;}* * public String productFamily {get;set;}* * public String productLine {get;set;}* * public String productSubLine {get;set;}* * public String productCategory {get;set;}* * public Decimal priceCad {get;set;* * public Decimal priceEur {get;set;} * * public Decimal priceGbp {get;set;} * * public Decimal priceInr {get;set;} * * public Decimal priceJpy {get;set;} * * public Decimal priceUsd {get;set;}* And here is a fragment of my displayed list just to amplify the concept; it just shows 2 currency amounts instead of all 6 just to make it clearer. [image: ref01.png] So I just want to use the same “draft values” approach that is standard for the datatable component to update the appropriate sObjects, as below: [image: ref02.png] And here is the standard “Save” function (from another project; NOT this one) which I am sure most of you have seen, and which uses the uiRecordApi to implement, without any Apex call. *handleSave(event) {* * const recordInputs = event.detail.draftValues.slice().map(draft => {* * const fields = Object.assign({}, draft);* * return { fields };* * });* But in my application I know that I need to imperatively call my Apex class to handle this update, and I can do that. I am currently only passing back the JSONified values of the “draftValues” and the entire list itself, just to see how that works: *handleSave(event) {* * var draftValuesStr = JSON.stringify(event.detail.draftValues);* * var wrapList = JSON.stringify(this.pricesList);* * updatePriceRecords({updateObjStr: draftValuesStr, wrapList: wrapList});* * }* And this does bring back the “draft” values perfectly for me, as you can see below: *[{"priceUsd":"456.00","priceEur":"765.67","Id":"row-3"}]* And my Apex could handle the price updates if ONLY it had some unique ID (like the product number, in my case), so that is what I am asking how to do. All the string contains as an ‘ID’ is the row ID, which is not very helpful. I know that I can bring back the ENTIRE list, and then be able to associate the row ID with the appropriate record in the list and get the product number that way, but that is clearly a horribly inefficient idea, and there has got to be a better way. I also considered somehow persisting my list into a CACHE (like a user setting?) so I could retrieve the original list that way, but that does not sound like a good idea either. Also, I am thinking that I could somehow iterate through the JSONified draft values and insert the product ID appropriately into that list, but I am not sure how I would go about grabbing the product ID out of the selected record in the list. If anybody could help me out with this I would really appreciate it. It seems to me that this would be a very common use case out there. Thanks very much.
Abhishek BansalAbhishek Bansal
I already replied to your question.Please check.