[SalesForce] Pass record value to controller using lightning component

I'm new to using lightning and am writing a component that overrides a custom object detail button. I'm able to successfully override the detail view with my component using: <force:recordView recordId="{!v.recordId}" type="FULL"/>

I have two buttons that I have added, which call action methods in my apex controller. Each button returns a record id that I will use to navigate to when the methods are executed.

My question, is how can I pass a value to my action method from the recordView?

Here is my component:

<aura:component implements="lightning:actionOverride,force:hasRecordId,force:hasSObjectName" controller="SSOViewOverrideController" access="global">
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/> 
<div class="slds-card">
    <div class="slds-m-around--xx-large">
        <div class="slds-form--stacked">
            <div class="slds-m-around--medium">
                <button class="slds-button slds-button--brand" onclick="{!c.gotoContact}">Go To Contact</button>
                <button class="slds-button slds-button--brand" onclick="{!c.createCase}">Create Case</button>
            </div>
        </div>
    </div>
    <lightning:recordEditForm recordId="{!v.recordId}" objectApiName="SSO__x" />
</div> 
</aura:component>

Here is my component controller:

({
 doInit: function(cmp) {
     var navEvt = $A.get("e.force:navigateToSObject");
     navEvt.setParams({
         "recordId": cmp.get("v.recordId"),
         "slideDevName": "detail"
     });
     navEvt.fire();      
}, 
gotoContact: function(cmp) {
    var action = ccmp.get('c.getContact'); 
    action.setParams({ guidId : cmp.get("v.guid__c") });
},
createCase: function(cmp) {

}
})

Here is my apex controller action method:

@auraEnabled
public static Id getContact(string guidId) {
    Id retval;
    Contact[] cList = CreateCaseContactUtil.searchContactByGUID(guidId);
    if(cList.size() > 0) {
        retval = cList[0].Id;
    }
    return retval;
}

I need to pass the record field value guid__c into my apex controller action method, which returns a contact Id that I will then want to navigate to that record when the button is clicked.

The recordView is showing the guid__c value on the page, but have not been able to pass it to my action method and get the id back to navigate to contact record.

Best Answer

If I am reading your implementation right, then you have got few things wrong here in your implementation. You are not really viewing what is in your component, rather when your component is initialized, you are actually redirecting the flow using force:navigateToSobject in your donInit function to the record id mentioned in the function. So you never are in your component.

Going back to force:recordView, it is a read only representation and does not let you to fetch any further details on the rendered layout viz., fetch specific field values from the view. Though you will have access to the body of the component, but traversing through it to find a field's value will be more cumbersome. If you refer to the documentation, it mentions as below.

If you want granular control over displaying of specific fields, we recommend using lightning:outputField instead.

As for your issue of passing a value from your view to the controller, you have got couple of options.

Option 1 - Modification in your current implementation

Assuming that you want a detail layout using force:recordView, you can make a server call in your doInit function to fetch the guid field and populate it on your component. And then when you click the button, use this field's value to pass on to apex controller. Your code will look something like this:

Attribute declaration on component:

<aura:attribute name="guid" type="String" />

In your existing doInit, modify it as:

doInit: function(cmp, event, helper) {
    var action = cmp.get('c.getGUID');
    action.setParams({ recordId : cmp.get("v.recordId") }
    action.setCallback(this, function(response) {
        var state = response.getState();
        if (state === "SUCCESS") {
            cmp.set("v.guid", response.getReturnValue()); // you are setting the guid from server here
        }
    });
    $A.enqueueAction(action);
}

And in your apex controller:

@auraEnabled
public static String getGUID(String recordId) {
    // select guid from sso__x where id = :recordId;
    // return the guid as retrieved
}

Now you have guid available with your component as an attribute on it, which you can use anywhere in any of the JS function.

So when you click the button, you can fetch the guid in your JS function:

gotoContact: function(cmp) {
    var action = ccmp.get('c.getContact'); 
    action.setParams({ guidId : cmp.get("v.guid") }); // notice this line
    // call your apex method
    // use navigateToSobject here to redirect to the contact id as retrieved.
}

Using this approach, you are using recordView along with a bit of your customization. However note that this may not be most efficient way as this approach is actually making a server trip twice, once for loading the fields with record view and then in your doInit function. But with this approach you easily achieve the detail layout functionality without writing anything around how to render the fields.

Option 2 - Implement using lightning:recordEditForm

With this approach, you will need to write all your fields which you want to display on the page. You can use lightning:inputField with some styling to make it read only, so that it aligns with detail layout, associate the input fields with an aura:id and then retrieve the values in your JS function. You can find more details using lightning:recordEditForm and how to fetch values from it in JS function in this answer here.

Related Topic