0

I've got this helper method with two functions in it. One function that creates a lead and another function to load a specific record where the recently created lead is populated on a lookup field. These two functions reside on the same onclick button and I need them to run one after another. How would I make them run

I somehow need to have a the record loaded once the lead has been created. Do I load the loadBaseRecord in a callback? If so, how?

Function to create the lead:

createBaseLead: function(component, event, helper) {
    component.find("accountRecordCreator").saveRecord(function(saveResult) {
        if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
            // record is saved successfully
            var customerAccountId = saveResult.recordId; // Gets the record ID of the account created
            var appEvent = $A.get("e.c:CustomerSubmitForm");
                    appEvent.setParams({
                        customerAccountId: customerAccountId // customerAccountId in the CustomerSubmitForm event is now set to the ID that was just created
                    });
            appEvent.fire(); // Fires the event to store customerAccountId in the Event "CustomerSubmitForm.evt"
            console.log(customerAccountId);

            //Load Sales App Record


            var resultsToast = $A.get("e.force:showToast");

            resultsToast.setParams({
                "title": "Saved",
                "message": "The record was saved."
            });
            resultsToast.fire();
        }
        else if (saveResult.state === "INCOMPLETE") {
            // handle the incomplete state
            console.log("User is offline, device doesn't support drafts.");
        }
        else if (saveResult.state === "ERROR") {
            // handle the error state
            console.log('Problem saving contact, error: ' + JSON.stringify(saveResult.error));
            var resultsToast = $A.get("e.force:showToast");
            resultToast.setParams({
                "title": "Error",
                "message": "Please complete the form"
            })
            resultsToast.fire();
        }
        else {
            console.log('Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error));
        }
    });
},

Function to load the record:

 loadBaseRecord: function(component, event, helper) {
var event = $A.get("event.force:createRecord");

                if (event) {
                    event.setParams({
                        entityApiName: "Sales_Appointment__c",
                        defaultFieldValues: {
                            Resource__c: component.get("v.resourceId"),
                            Dealership__c: component.get("v.accountId"),
                            Lead__c: component.get("v.customerAccountId"),

                        }
                    })
                    event.fire();
                }
                else {
                    alert("Not available")
                }
    },

Lead__c: component.get("v.customerAccountId"),

in the loadBaseRecord function is where the Lead will be populated

  • Possible duplicate of How do I enqueue an action after receiving value from first action lightning controller. Check the answer on this link, if this is what you need. – Jayant Das Apr 20 '18 at 11:51
  • I looked at that one, but I'm not really calling a server-side controller so I'm not sure how to write this syntatically – erikvm Apr 20 '18 at 11:55
  • You may not be calling a server side controller, its more about calling a JS function from callback of another. Also when you say this -- One function that creates a lead and another function to load a specific record where the recently created lead is populated on a lookup field -- how are you associating the "specific record" with the new lead created in your flow? Are you also creating the specific record along with? – Jayant Das Apr 20 '18 at 12:18
  • So, the record that is being loaded is an appointment record. On that appointment record, there is a lookup field to Lead (which in this case is the customer). Previously, I had a form where a lead is submitted with Lightning Data service --> once you hit "submit", that record ID is stored in an event, I can then use that record ID for the appointment record. However, I'm trying to remove the "submit" button on creating the lead and instead just automatically have a lead created and loading the appointment record, all in one button – erikvm Apr 20 '18 at 12:43
  • You may not need to have two calls/functions to achieve this then. You can address both of this in a single apex call. On click of submit, in your apex, you first create the lead, use its id to create a new appointment record, and then return the details from appointment (and/or lead) from your apex back to your JS to be rendered in the component. – Jayant Das Apr 20 '18 at 12:52
1

Consider a promise chain. It's possible to string together many serverside callouts and then easily understand their order. If you nest helpers within helpers you get into callback hell.

See here: https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/js_promises.htm

This is a formatting sample of a complicated promise chain I am currently using to initialize a lightning:treeGrid dynamically:

Helper:

initTreeGridPromiseChain : function(component) {
  let _self = this;

  _self.fetchTreeGridColumnsPromise(component)
      .then(
        // resolve handler
        $A.getCallback(function(result) {
          return _self.fetchOrderDataPromise(component);
        }),
        // reject handler
        $A.getCallback(function(error) {
          console.log("Promise 1 was rejected: ", error);
        })
      )
      // Fetch parent row only first, in case children take a while to load
      .then(
        // resolve handler
        $A.getCallback(function(result) {
          return _self.fetchParentWrapperDataPromise(component);
        }),
        // reject handler
        $A.getCallback(function(error) {
          console.log("Promise 2 was rejected: ", error);
        })
      )
      // Parents are fetched twice because it's easier to create the _children relationship serverside
      .then(
        // resolve handler
        $A.getCallback(function(result) {
          if (component.get("v.orderedRowTypes").length > 1) {
            return _self.fetchParentWithNestedChildWrapperDataPromise(component);
          }
        }),
        // reject handler
        $A.getCallback(function(error) {
          console.log("Promise 3 was rejected: ", error);
        })
      )
      .catch(function(error) {
        $A.reportError("error message here", error);
      });
},
0

If you need to execute your code functions in a particular order, the only way is to call the 2nd function from the callback of 1st function. It's called Chanining.

In you case, you can call the function loadBaseRecord from the callback of createBaseLead as below(using this operator).

  createBaseLead: function(component, event, helper) {
    component.find("accountRecordCreator").saveRecord(function(saveResult) {
        if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
            // record is saved successfully
            var customerAccountId = saveResult.recordId; // Gets the record ID of the account created
             var appEvent = $A.get("e.c:CustomerSubmitForm");
                    appEvent.setParams({
                        customerAccountId: customerAccountId // customerAccountId in the CustomerSubmitForm event is now set to the ID that was just created
                    });
            appEvent.fire(); // Fires the event to store customerAccountId in the Event "CustomerSubmitForm.evt"
            console.log(customerAccountId);

             //Load Sales App Record
            this.loadBaseRecord(component, event, helper,customerAccountId)



            var resultsToast = $A.get("e.force:showToast");

            resultsToast.setParams({
                "title": "Saved",
                "message": "The record was saved."
            });
            resultsToast.fire();
        }
        else if (saveResult.state === "INCOMPLETE") {
            // handle the incomplete state
            console.log("User is offline, device doesn't support drafts.");
        }
        else if (saveResult.state === "ERROR") {
            // handle the error state
            console.log('Problem saving contact, error: ' + JSON.stringify(saveResult.error));
            var resultsToast = $A.get("e.force:showToast");
            resultToast.setParams({
                "title": "Error",
                "message": "Please complete the form"
            })
            resultsToast.fire();
        }
        else {
            console.log('Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error));
        }
    });
},

loadBaseRecord: function(component, event, helper, customerAccountId) {
var event = $A.get("event.force:createRecord");

                if (event) {
                    event.setParams({
                        entityApiName: "Sales_Appointment__c",
                        defaultFieldValues: {
                            Resource__c: component.get("v.resourceId"),
                            Dealership__c: component.get("v.accountId"),
                            Lead__c: customerAccountId,

                        }
                    })
                    event.fire();
                }
                else {
                    alert("Not available")
                }
    }
  • Doing it this way won't work because the lead never has a chance to actually get created, and if I try to load the record where the Lead will reside, it will just throw an error saying Lead does not exist.. I think I somehow need to enqueue the action – erikvm Apr 20 '18 at 12:31
  • It should work cause you are calling the the loadBaseRecord in the callback function of saveRecord. First the record is saved and then you will be invoking the loadBaseRecord from callback function. Can you try it once and let me know? – Bhawna Apr 20 '18 at 12:43
  • I'm just getting an error because the lead is not found. (Getting some generic error). Don't I need to enqueue it somehow? – erikvm Apr 20 '18 at 13:22
  • I would assume it has to do with the fact that the function calls are called one after another, but the "createBaseLead" hasn't finished receiving a record ID yet to populate in the function for "loadBaseRecord", so somehow I need to make sure that createBaseLead is completely done before kicking off the other function.. – erikvm Apr 20 '18 at 13:33
  • Well... This is strange. Coz as per the documentation component.find("accountRecordCreator").saveRecord(function(saveResult) is callback function. I will try this in my local org myself. will let you know once I find something. – Bhawna Apr 20 '18 at 13:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.