+ Start a Discussion
Ben Beisswenger 4Ben Beisswenger 4 

Apex Method from Lightning Component

Hi! I'm trying very hard to figure out how to make this Apex Action run directly from a Lightning Component. We used to run it from a VF page but it's ugly.

Does anyone know how to do this? I @AuraEnabled the method within the Apex class, and Identified the controller in the header. But it says there's an "Uncaught Unknown controller action 'getkickoffworkflow'"

 
Jayant DasJayant Das
Can you post the sample code here?
Ben Beisswenger 4Ben Beisswenger 4
Sure!

--COMPONENT--
ExecutiveSummary.cmp

<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId,force:lightningQuickAction" access="global" controller="ExecutiveSummary">
    <aura:attribute name="opp" type="Opportunity" 
                    description="The record object to be displayed"/>
    <aura:attribute name="recordError" type="String" 
                    description="Can't find Record"/>
    <aura:attribute name="opId" type="string"/>
    
    <force:recordData aura:id="Opportunity"
                      layoutType="FULL"
                      recordId="{!v.recordId}"
                      targetError="{!v.recordError}"
                      targetRecord="{!v.record}"
                      targetFields="{!v.simpleRecord}"
                      mode="VIEW"/>
        
    <aura:set attribute="opId" value="v.recordId"/>
    
    <lightning:button label="TEST"
            onclick="{!c.getkickoffworkflow}"/>
</aura:component>


--APEX CLASS--
ExecutiveSummary.apxc

public class ExecutiveSummary {


private final Opportunity opt;
    public ExecutiveSummary(ApexPages.StandardController stdController) {
        
        this.opt = (Opportunity)stdController.getRecord();
        
    }

    @AuraEnabled
    public void getkickoffworkflow(){
        string workflowXML = '<salesforce>'; 
        
        workflowXML += '<opportunityID>' + this.opt.Id + '</opportunityID>'; 
        workflowXml += '</salesforce>'; 
        
        //This line of code creates the SpringCM workflow Object, and is targeting the workflow 
        // specified in the first argument, which is 'SpringCM Workflow Name', in this example 
        SpringCMWorkflow workflow = new SpringCMWorkflow('Executive Summary Automation', workflowXml); 
        
        //This example includes Test code as well. This is important as SFDC requires that 75% 
        // code coverage by testing to deploy or package Apex. 
        if (!Test.isRunningTest()) {
        //Moved inside if-block because when the SpringCMService object is instantiated,
        //a SpringCMApiEnvironment object is queried for, which while testing, causes a
        //query exception, causing the test to fail.    
        SpringCMService springcm = new SpringCMService(); 
        //The below line starts the workflow object that was created. 
        workflow = springcm.startWorkflow(workflow); 
        }
    }
}
Jayant DasJayant Das
The c.getkickoffworkflow needs to invoke the component's JS controller function. The JS function will then invoke the aura apex method. I assume you have it implemented that way. If not, you can find more on invoking aura enabled apex methods here -- https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/controllers_server_actions_call.htm
Sunil MadanaSunil Madana
Hi Ben,
In addition to what Jayant had mentioned above, your code will work if it is like below:

Component code:
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId,force:lightningQuickAction" 
                access="global" controller="ExecutiveSummary">
    <aura:attribute name="opp" type="Opportunity" description="The record object to be displayed"/>
    <aura:attribute name="simpleRecord" type="Object" description="A simplified view record object to be displayed"/>
    <aura:attribute name="recordError" type="String" description="Can't find Record"/>
    <aura:attribute name="opId" type="string"/>
    
    <force:recordData aura:id="opp"
                      layoutType="FULL"
                      recordId="{!v.recordId}"
                      targetError="{!v.recordError}"
                      targetRecord="{!v.opp}"
                      targetFields="{!v.simpleRecord}"
                      mode="VIEW"/>
    
    <aura:set attribute="opId" value="v.recordId"/>
    
    <lightning:button label="TEST" onclick="{!c.callkickoffworkflow}"/>
</aura:component>
Component controller;
({
    "callkickoffworkflow" : function(cmp) {
        // create a one-time use instance of the serverEcho action
        // in the server-side controller
        var action = cmp.get("c.getkickoffworkflow");
        action.setParams({ oppId : cmp.get("v.recordId") });
        
        // Create a callback that is executed after 
        // the server-side action returns
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                // Alert the user with the value returned 
                // from the server
                alert("From server: " + response.getReturnValue());
                
                // You would typically fire a event here to trigger 
                // client-side notification that the server-side 
                // action is complete
            }
            else if (state === "INCOMPLETE") {
                // do something
            }
                else if (state === "ERROR") {
                    var errors = response.getError();
                    if (errors) {
                        if (errors[0] && errors[0].message) {
                            console.log("Error message: " + 
                                        errors[0].message);
                        }
                    } else {
                        console.log("Unknown error");
                    }
                }
        });
        
        // optionally set storable, abortable, background flag here
        
        // A client-side action could cause multiple events, 
        // which could trigger other events and 
        // other server-side action calls.
        // $A.enqueueAction adds the server-side action to the queue.
        $A.enqueueAction(action);
    }
})
Apex Class:
public class ExecutiveSummary {
    
    @AuraEnabled
    public static String getkickoffworkflow(String oppId) {
        string workflowXML = '<salesforce>'; 
        
        workflowXML += '<opportunityID>'+oppId+'</opportunityID>'; 
        workflowXML += '</salesforce>'; 
        
        //This line of code creates the SpringCM workflow Object, and is targeting the workflow 
        // specified in the first argument, which is 'SpringCM Workflow Name', in this example 
        SpringCMWorkflow workflow = new SpringCMWorkflow('Executive Summary Automation', workflowXml); 
        
        //This example includes Test code as well. This is important as SFDC requires that 75% 
        // code coverage by testing to deploy or package Apex. 
        if (!Test.isRunningTest()) {
            //Moved inside if-block because when the SpringCMService object is instantiated,
            //a SpringCMApiEnvironment object is queried for, which while testing, causes a
            //query exception, causing the test to fail.    
            SpringCMService springcm = new SpringCMService(); 
            //The below line starts the workflow object that was created. 
            workflow = springcm.startWorkflow(workflow); 
        }
        return workflowXML;
    }
}
Refer to the In addition paragraph in the below URL;
http://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/controllers_server_apex.htm

Your methods must static and your previous code was like below and did not return an object:
public class ExecutiveSummary {


private final Opportunity opt;
    public ExecutiveSummary(ApexPages.StandardController stdController) {
        
        this.opt = (Opportunity)stdController.getRecord();
        
    }

    @AuraEnabled
    public void getkickoffworkflow(){
        string workflowXML = '<salesforce>'; 
        
        workflowXML += '<opportunityID>' + this.opt.Id + '</opportunityID>'; 
        workflowXml += '</salesforce>'; 
        
        //This line of code creates the SpringCM workflow Object, and is targeting the workflow 
        // specified in the first argument, which is 'SpringCM Workflow Name', in this example 
        SpringCMWorkflow workflow = new SpringCMWorkflow('Executive Summary Automation', workflowXml); 
        
        //This example includes Test code as well. This is important as SFDC requires that 75% 
        // code coverage by testing to deploy or package Apex. 
        if (!Test.isRunningTest()) {
        //Moved inside if-block because when the SpringCMService object is instantiated,
        //a SpringCMApiEnvironment object is queried for, which while testing, causes a
        //query exception, causing the test to fail.    
        SpringCMService springcm = new SpringCMService(); 
        //The below line starts the workflow object that was created. 
        workflow = springcm.startWorkflow(workflow); 
        }
    }
}
Hope the above answer helps and please mark as correct answer so others can benefit from it.