3

I have a VF Page embedded on a Record-Home Flexipage in LEX. I'm using my own VF-Container-Iframe-LightningComponent to host it, but since using the magic parameter isdtp=p1 I get the platform provides me the sforce.one object, which can do very powerful things such a opening a popup to edit existing records:

sforce.one.editRecord(recordId);

It works like a charm and it looks like that

enter image description here

Now when I press save is see this green toast:

enter image description here

But I found now way to trigger that this happen in order to execute an additional JS-function. I need that, because I have a Visualforce List and I use the sforce.one.editRecord() to modify records shown in the list. Of course after updating a record, I want to reload the list automatically to make sure that the user does not see any obsolete data.

What I have tried so far is just to call a function after the the invocation of sforce.one.editRecord() like this

sforce.one.editRecord(recordId);
console.log('afterEdit');

Unfortunately sforce.one.editRecord() acts asynchronously and return immediately and the console.log() is executed immediately and not after edit.

Is there any way to hack something to invoke a function after the edit has been completed?

I suppose that sforce.one.editRecord() is just a wrapper for the underlying $A.get('e.force:editRecord').setParams({recordId:recordId}).fire();

Now I found here How to find out when force:editRecord dialog is closed after saving changes? that it could be worth to try these events

  • force:recordSaveSuccess
  • force:showToast

which I could subscribe in my VF-container-IFRAME-LightningComponent (thank god I have used my own one!). But before I start a massive trial-and-error-session I would like to ask you guys if someone has successfully invoked anything "after save" either in a custom LC or in VF. In the other question above it seem unclear to me, if any of those events catch the SAVE properly. When I get some generic recipe, I can figure out the rest on my own.

I need the same for Lightning Components

Also I have the very same scenario in pure LCs: we often calculate standard Name fields by trigger or by ProcessBuilder. Now we can't get rid of the damn Name field in the layout, because it's required. Neither can we prepopulate it using the Standard "New" Button in LEX. Now overriding the New-Action with a custom LC, again I would need a way to act (reload, refresh, update) AFTER the SAVE has been executed.

So this question applies to VF as well as to LCs.

  • Did you ever figure this out with sforce.one? – Coova Feb 22 at 14:28
2

I believe we can subscribe to the record changes using force:recordData.

force:recordData has recordUpdated attribute which can be used to hook up a controller method which gets invoked when the record is changed using native framework supported actions / components / events / API like force events or components, lightning:recordForm, lightning:recordEditForm, standard / custom actions...

Below is the component which I placed on the Contact Detail page:

ContactView.cmp

<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" >

    <aura:attribute name="simpleRecord" type="Object"/>
    <aura:attribute name="recordError" type="String"/>

    <force:recordData aura:id="recordLoader"
        recordId="{!v.recordId}"
        layoutType="FULL"
        targetRecord="{!v.record}"
        targetFields="{!v.simpleRecord}"
        targetError="{!v.recordError}"
        recordUpdated="{!c.recordUpdated}"
    />

    <button onclick="{!c.editRecord}" > Edit </button>
</aura:component>

ContactViewController.js

({
    recordUpdated: function(component, event, helper) {

        var changeType = event.getParams().changeType;
        console.log(changeType);
        if (changeType === "ERROR") { /* handle error; do this first! */ }
        else if (changeType === "LOADED") { /* handle record load */ }
        else if (changeType === "REMOVED") { /* handle record removal */ }
        else if (changeType === "CHANGED") { /* handle record change */ }

    },
    editRecord: function(component, event, helper) {
        var evt = $A.get("e.force:editRecord");
        evt.setParams({"recordId" : component.get("v.recordId")});
        evt.fire();
    }
})
1

For me it worked by subscribing force:showToast inside my custom IFRAME lightning component which is hosting the VF Page:

<aura:handler event="force:showToast" action="{!c.forceShowToastHandler}" />

and in the controller

forceShowToastHandler : function(cmp, evt, hlp){
    // my custom invocation comes here
},

This pattern should work for pure-LC using

$A.get('e.force:editRecord').setParams({recordId:recordId}).fire(); 

in the same way.

Right now I'm refreshing my stuff on every toast I get, since I haven't figured out on how to identify the relevant toasts and distinct them from irrelevant toasts. This might lead to unnecessary or unwanted refreshes, but it is way better than nothing ;-)

I will keep this question open for now, because I think there could be better solution than mine, which I would consider still as "very dirty". If there is no better solution, I would be happy if Salesforce could become aware, that the $A.get('e.force:editRecord') should be extended in a way so that we can provide a callback to act on AFTER SAVE or provide some better event which we can subscribe than the "toast". The result would be so much cleaner.

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.