[SalesForce] Link to new SObject page from list view button in Lightning with defaulted fields

My org just recently switched from Classic to Lightning, and there's one limitation I'm having a lot of trouble working around. Before the transition, we had a lot of URL hack buttons linking to the standard page to create a new record. These, while not technically supported, worked just fine in classic, but break in LEX.

For the buttons at the top of the page, I've used Lightning Component quick actions that fire $A.get("event.force:createRecord") using defaultFieldValues in the params, which has worked like a charm. However, we have many of these buttons at the related list level, and in this case, custom Lightning Component buttons are not supported. (See this question. Also, on the roadmap, there is no planned release date yet as of May 2019 when I'm writing this.)

My first attempt was to create a URL button to link to a Visualforce page and use Lightning Out to embed the component that initiated the link, similar to what was described in this question. However, I'm back to square one, because I need to redefine the link in the javascript. If I navigate to a URL, I can't default the fields for the same reason I couldn't use the original button to begin with. Additionally, all navigation methods (as far as I know, anyway) in vanilla JS do not support defaulting.

Next, I tried to do the same thing with a direct link to a Lightning App from the URL button – like /c/MyLightningApp. However, I still needed to add the same <aura:dependency resource="markup://force:*" type="EVENT"/> to avoid an error, and when I did, the events seemed to be undefined in the way they would be in a VF page. Am I missing something?

Link, on URL list button on the related list of a custom object on the Opportunity page layout: /c/CreateRecord_App.app?accId={!Opportunity.AccountId}&oppId={!Opportunity.Id}

Lightning App:

<aura:application>
    <aura:attribute name="accId" type="String"/>
    <aura:attribute name="oppId" type="String"/>
    <c:CreateRecord accountId="{!v.accId}" opportunityId="{!v.oppId}"/>
    <aura:dependency resource="markup://force:*" type="EVENT"/> <!--When I didn't include this, it errored-->
</aura:application>

Lightning Component

<aura:component>
    <aura:attribute name="opportunityId" type="String"/>
    <aura:attribute name="accountId" type="String"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
</aura:component>

Lightning Controller

({
    doInit : function(component, event, helper){
        var createRecordEvent = $A.get("event.force:createRecord");
        createRecordEvent.setParams({
            entityApiName: "Custom_Object__c"
            , defaultFieldValues: {
                Opportunity__c: component.get("v.opportunityId")
                , Account__c: component.get("v.accountId")
            }
        });
        //These are being populated correctly
        console.log(component.get("v.opportunityId"));
        console.log(component.get("v.accountId"));
        createRecordEvent.fire();
    }
})

At this point, I'm stuck. Is there something I'm missing in the approach above? Why would I need to define the dependency on an entirely Lightning-based approach, and why would I be unable to use the event functionality?

Also, is there a completely different approach to solving this dilemma that's eluding me?

Best Answer

For list buttons I would suggest using URL buttons in combination with lightning:isUrlAddressable interface. Using a component you are not moving outside of standard Lightning Application so there is no need to add any dependencies. So your url would look something like that:

/lightning/cmp/c__CreateRecord?c__accId={!Opportunity.AccountId}&c__oppId={!Opportunity.Id}

Remember to add your namespace (probably c__) before component's name and it's attributes. After this critical update was activated attributes without namespace are removed from pageReference's state.

Related Topic