Call Method of Child from Parent – Reusable Component in Lightning

In this post, we will implement the functionality to call a method of Child component from Parent and how to make a Reusable Component in Lightning. To call a method of Child Component from Parent, we need to make use of <aura:method>.

<aura:method> executes in a Synchronous manner and hence it is easy to return a value from <aura:method>. But if we are handling Asynchronous code in <aura:method>, it becomes a little tricky. We will implement both scenarios. So let’s hop into the implementation.

Implementation

In this implementation, we will create a Child Component AccountUtility which will have multiple reusable methods to create and update the Account record. Parent Component AccountManager will call the methods of Child Component AccountUtulity to create and update the Account record.

Call Method of Child from Parent in Lightning
Call Method of Child from Parent in Lightning

First, create an AccountUtility component and add two <aura:method> to create and update the Account. We can provide the following attributes to <aura:method>.

  • name: The method name to call it from Parent.
  • action: Client-side action that will be executed.
  • access: Public to restrict for the same namespace. Global for all namespaces.
  • description: Method description.

If we want to pass parameters, we can use <aura:attribute> inside <aura:method> and pass the required parameters.

AccountUtility.cmp

<aura:component controller="AccountUtility">
	<aura:method name="createAccount" action="{!c.createAccount}" description="To create new Account"> 
        <aura:attribute name="objAccount" type="Account"/>
        <aura:attribute name="callback" type="Function"/>
    </aura:method>
    <aura:method name="updateAccount" action="{!c.updateAccount}" description="To update existing Account"> 
        <aura:attribute name="objAccount" type="Account"/> 
    </aura:method>
</aura:component>

AccountUtilityController.js

({
	createAccount : function(component, event, helper) {
        var params = event.getParam('arguments');
		helper.createAccountHelper(component, event, params.objAccount, params.callback);
	},
    
    updateAccount : function(component, event, helper) {
		helper.updateAccounttHelper(component, helper, params.objAccount);
	}
})

We will call Apex Methods from the helper to create and update the Account record.

AccountUtilityHelper.js

({
	createAccountHelper : function(component, event, objAccount, callback) {
		var action = component.get("c.createAccountRecord");
        action.setParams({
            accRecord : objAccount
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                var result = response.getReturnValue();
                if(callback){
                    callback(result);
                }
            }
            else {
                console.log("Failed with state: " + state);
            }
        });
        $A.enqueueAction(action);
	},
    
    updateAccounttHelper : function(component, event, objAccount) {
		var action = component.get("c.updateAccountRecord");
        action.setParams({
            accRecord : objAccount
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                var result = response.getReturnValue();
                
                // Perform Post Update logic
            }
            else {
                console.log("Failed with state: " + state);
                return state;
            }
        });
        $A.enqueueAction(action);
	}
})

AccountUtility.apxc

public class AccountUtility {
	@AuraEnabled
    public static String createAccountRecord(Account accRecord){
        insert accRecord;
        return accRecord.Id;
    }
    
    @AuraEnabled
    public static void updateAccountRecord(Account accRecord){
        update accRecord;
    }
}

Call Method of Child from Parent

Now, in Parent Component AccountManager, add input text boxes and a button to create an Account record. Also include Child Component AccountUtility with aura:id.

AccountManager.cmp

<aura:component controller="AccountManager" implements="flexipage:availableForAllPageTypes">
    <aura:attribute name="objAccount" type="Account" default="{
                                                                  Name : '',
                                                                  AccountNumber: '',
                                                                  Phone : '',
                                                                  Website : ''
                                                              }"/>
    <aura:attribute name="recentId" type="String"/>
    <c:AccountUtility aura:id="accountUtility"/>

    <lightning:card title="Account Manager">
        <div class="slds-p-around_small">
            Recent Account Id: <lightning:formattedText value="{!v.recentId}" />
            <lightning:input name="Name" label="Name" value="{!v.objAccount.Name}"/>
            <lightning:input name="Account Number" label="Account Number" value="{!v.objAccount.AccountNumber}"/>
            <lightning:input name="Phone" label="Phone" value="{!v.objAccount.Phone}"/>
            <lightning:input name="Website" label="Website" value="{!v.objAccount.Website}"/>
            <br/>
            <lightning:button variant="brand" label="Create Account" onclick="{!c.createAccount}" />
        </div>
    </lightning:card>
</aura:component>

In JS Controller, we will get the instance of AccountUtility component using component.find() and call the createAccount() of Child component like below:

const accountUtility = component.find('accountUtility');        
accountUtility.createAccount(param1, param2);

where param1 and param2 are the parameters that we are passing to the createAccount method of Child Component. And this is enough to call the method of Child from Parent Component. We can also return some value from the methods of Child Component.

But what if we are executing Asynchronous code in Child Method? We might need a return value from the Asynchronous code. As our <aura:method> runs in a Synchronous mode, it will not wait for Asynchronous code to execute. And we will never get a return value from the Asynchronous method in our Parent Component.

To handle this, we have added one more attribute in our createMethod in AccountUtility component to pass the callback function.

<aura:method name="createAccount" action="{!c.createAccount}" description="To create new Account"> 
        <aura:attribute name="objAccount" type="Account"/>
        <aura:attribute name="callback" type="Function"/>
    </aura:method>

Now, in the JS Controller, we will pass two parameters; accRecord and a callback function as a parameter.

AccountManagerController.js

({
    createAccount: function (component, event, helper) {
        var accRecord = component.get('v.objAccount');
        const accountUtility = component.find('accountUtility');
        
        accountUtility.createAccount(accRecord, function(result){
        	component.set('v.recentId', result);
        });
    }
});

Now, refer to the createAccountHelper() of AccountUtilityHelper.js, we are calling the Apex method to create Account which executes in an Asynchronous manner. Once we get the state as SUCCESS in the callback method of Apex method, we are calling callback(result) which will call the callback method in our Parent Component and pass the result as a parameter. In this way, we can return a value from the <aura:method> which has Asynchronous code. Once the Account is created, we are returning the Id of the new Account and showing it in a Parent Component.

This is how our implementation looks:

Reusable Component in Lightning
Reusable Component in Lightning

Reusable Component in Lightning

AccoutUtility Component is the Reusable Component we created in Lightning. We have put two methods to create and update the Account records. In this way, we can create any number of methods in one Lightning Component without any markup in the Cmp file.

Then, we can include this Component in any other Lightning Component as a Child Component. As explained earlier, we can call the methods of this Reusable (Child) Component from Parent Component to make it a Reusable Component in Lightning.

In this way, we can Call Method of Child from Parent and make Reusable Component in Lightning. If you don’t want to miss a new implementation, please Subscribe here.

If you want to check more implementations in Lightning, you can check it here.

To know more about <aura:method>, you can check official Salesforce documentation here.

See you in the next implementation!