I am trying to override the standard button on the related list of Quote object using a lightning component [compA]. For some reason, the record id is undefined even if I have force:recordId and an attribute. I would need the recordId to prepopulate a field on my lightning component form and for redirection after the user hits save button. I created another lightning component that displays the record Id and placed it on the Quote record page just for testing and it successfully displays the id. Is there a way for me to get the record Id on my lightning component [compA]?
2 Answers
You'll have to pass the record Id to your aura component to have it.
Why?
When your component is invoked in a record context in Lightning Experience or the Salesforce mobile app, the recordId is set to the ID of the record being viewed.
Clicking the "new" button on a related list opens a new page context (it'll be in its own tab) - in this case, it opens the Aura component away from the record (Quote). It no longer has the context of a record page and that is why you have no record Id.
Your test (LWC on Quote record page), which has a record context, and your situation (button on related list that opens new tab) are not the same conditions - hence, why you get different results.
You'd have to leverage a URL button (List Button) on the related list for this to work in that capacity. On the related list, you'd show your custom button and and hide the standard new button.
To do the URL part, you need to leverage IsUrlAddressable so you can use a link to call your Aura component with values - so you'll pass the record Id before it re-directs to your URL from the related list.
Your URL will be /lightning/cmp/c__componentname?c__quoteId={!Quote.Id}
<!--
make sure to implement it to be url addressable
as well as available for all page types
-->
<aura:component implements="lightning:isUrlAddressable,flexipage:availableForAllPageTypes">
<aura:attribute name="quoteId" type="String" />
<!-- Add an "init" handler to handle the first "v.pageReference" value -->
<aura:handler name="init" value="{!this}" action="{!c.onPageReferenceChange}"/>
<!-- Add a "change" handler to handle all changes to the "v.pageReference" value -->
<aura:handler name="change" value="{!v.pageReference}" action="{!c.onPageReferenceChange}"/>
({
onPageReferenceChange: function(cmp, evt, helper) {
var myPageRef = cmp.get("v.pageReference");
var quoteId = myPageRef.state.c__quoteId;
cmp.set("v.quoteId", quoteId);
}
})
-
Hi @Kris thank you for your answer! I tried the approach above but whenever my button is clicked, I am being redirected to a page with "This page isn't available in Salesforce Lightning Experience or mobile app". Though I am seeing in the url that it has the correct account Id. Any idea what could went wrong?– CharlieCommented Mar 24, 2022 at 14:22
-
Did you implement isUrlAddressable on the aura component?
<aura:component implements="lightning:isUrlAddressable">
Commented Mar 24, 2022 at 14:24 -
-
apologies, I edited the answer. You just need to implement
flexipage:availableForAllPageTypes
as well. Commented Mar 24, 2022 at 15:14
I think I've found the solution for this issue. Prior solution posted works, in standard sales navigation. But, when navigating on Salesforce Console, the parameter myPageRef.state.c__quoteId contains the Id of the main tab record, not the Id of the record where the related list button was pressed. For instance: in console navigation, user opens an Account page, from this account, opens a Contact record (It opens as a subtab of account), and then, goes to create a Case in the contact related list. In this case, the parameter myPageRef.state.c__ would contain the Account Id instead of contact Id. In order to get the actual record Id, you need to do this: URL contains the needed data, all you have to do is to decode it:
initComponent : function(component, event, helper) {
let recordId = component.get('v.recordId')
console.log('CreateCaseAction2 - recordId - ',recordId);//This is undefined
let urlData = component.get('v.pageReference');//parsed URL as JSON
if(urlData.state != undefined && urlData.state.inContextOfRef != undefined){
let inContextOfRaw = urlData.state.inContextOfRef;
let inContextOf = inContextOfRaw.split('.')[1];//This is a base64 encoded JSON which contains the data of the main tab record
console.log('CreateCaseAction2 - inContextOf - ',inContextOf);
let decoded = atob(inContextOf);//Decode the base64 encoded json
console.log('CreateCaseAction2 - decoded - ',decoded);
let decodedJson = JSON.parse(decoded);
console.log('CreateCaseAction2 - decodedJson - ',decodedJson);
//Shows:
//{
// "type": "standard__recordPage",
// "attributes": {
// "objectApiName": "Account",
// "recordId": "0011w00001lOeNpAAK",
// "actionName": "view"
// },
// "state": {}
//}
if(decodedJson.attributes != undefined && decodedJson.attributes.recordId != undefined){
console.log('CreateCaseAction2 - decodedJson.attributes.recordId - ',decodedJson.attributes.recordId);
component.set('v.recordId', decodedJson.attributes.recordId);//Sets the recordId
}
//Sets true a flag that displays the component where the recordId is actually needed.
//Otherwise, that componet will be shown BEFORE this method executes and it won't have the recordId
component.set('v.showData', true);
}
}
Finally, your component should be like this:
<aura:component controller="Utility" implements="flexipage:availableForRecordHome,lightning:isUrlAddressable,force:hasRecordId,force:hasSObjectName,lightning:actionOverride,force:lightningQuickActionWithoutHeader" access="global">
<aura:attribute name="recordId" type="String"/>
<aura:attribute name="showData" type="Boolean" default="false"/>
<aura:handler name="init" value="{!this}" action="{!c.initComponent}"/>
<aura:if isTrue="{!v.showData}">
<c:CreateRecordByRT recordId="{!v.recordId}" sObjectName="Case"/>
</aura:if></aura:component>
Hope it helps, at least for us, is working perfectly