Call Lightning Component from Flow

Call Lightning Component from Flow

In this section, we will call a Lightning Component from a Flow. Same Assignment: Create a Contact by Lightning Component calling from a Flow. To do this assignment, we will use Lightning Data Service.

Step 1: Create a component bundle named “createContactByLDS”.

createContactByLDS.cmp | to create contact using Lightning Data Service. To refer this component to flow, you must implement “lightning:availableForFlowScreens” at the component level.

<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId,lightning:availableForFlowScreens">

    <aura:attribute name="account" type="Object"/>
    <aura:attribute name="loadedAccountFields" type="Object"/>
    <aura:attribute name="accountError" type="String"/>

    <aura:attribute name="newContact" type="Object"/>
    <aura:attribute name="newContactFields" type="Object"/>
    <aura:attribute name="newContactError" type="String"/>
    

    <force:recordData aura:id="accountRecordLoaderId"
        recordId="{!v.recordId}"
        fields="Name"
        targetRecord="{!v.account}"
        targetFields="{!v.loadedAccountFields}"
        targetError="{!v.accountError}"
    />

    <force:recordData aura:id="contactRecordCreatorId"
        layoutType="FULL"
        targetRecord="{!v.newContact}"
        targetFields="{!v.newContactFields}"
        targetError="{!v.newContactError}" 
        /> 

    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

    <div class="slds-page-header" role="banner">
        <p class="slds-text-heading_label">{!v.loadedAccountFields.Name}</p>
        <h1 class="slds-page-header__title slds-m-right_small
            slds-truncate slds-align-left">Create New Contact</h1>
    </div>
    <lightning:card >
        <aura:if isTrue="{!not(empty(v.accountError))}">
            <div class="recordError">
                <ui:message title="Error" severity="error" closable="true">
                    {!v.accountError}
                </ui:message>
            </div>
        </aura:if>
        <aura:if isTrue="{!not(empty(v.newContactError))}">
            <div class="recordError">
                <ui:message title="Error" severity="error" closable="true">
                    {!v.newContactError}
                </ui:message>
            </div>
        </aura:if>

        <lightning:layout multiplerows="true" verticalalign="center">
            <lightning:layoutItem padding="around-small" size="12">
                <lightning:input aura:id="contactField" 
                                 name="firstName" 
                                 label="First Name"
                                 value="{!v.newContactFields.FirstName}"/>
              
                <lightning:input aura:id="contactField" 
                                 name="lastname" 
                                 label="Last Name"
                                 value="{!v.newContactFields.LastName}" 
                                 required="true"/>
                        
                <!--<lightning:input aura:id="contactField" 
                                 type="phone" 
                                 name="phone" 
                                 label="Phone Number"
                                 pattern="^(1?(-?\d{3})-?)?(\d{3})(-?\d{4})$"
                                 messageWhenPatternMismatch="The phone number must contain 7, 10, or 11 digits. Hyphens are optional."
                                 value="{!v.newContactFields.Phone}" 
                                 required="true"/>-->
                
                <lightning:input aura:id="contactField" 
                                 type="email" 
                                 name="email" 
                                 label="Email"
                                 value="{!v.newContactFields.Email}" />
                
                <div class="slds-float_right">
                    <lightning:button label="Reset" onclick="{!c.doReset}" class="slds-m-top_medium" />
                    <lightning:button label="Save" onclick="{!c.saveContact}"
                                      variant="brand" class="slds-m-top_medium"/>
                </div>                
           </lightning:layoutItem>
       </lightning:layout>    
    </lightning:card>
</aura:component>

createContactByLDSController.js | to save and reset the contact record

({
    doInit: function(component, event, helper) {
        helper.openNewContact(component);
    },

    saveContact: function(component, event, helper) {
        if(helper.validateContactForm(component)) {
            component.set("v.newContactFields.AccountId", component.get("v.recordId"));
            component.find("contactRecordCreatorId").saveRecord(function(saveResult) {
                if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {

                    var resultsToast = $A.get("e.force:showToast");
                    resultsToast.setParams({
                        "title": "Success! ",
                        "message": "The new contact was created.",
                        "type":"success"
                    });

                    $A.get("e.force:closeQuickAction").fire();
                    resultsToast.fire();

                    $A.get("e.force:refreshView").fire();
                    helper.openNewContact(component);
                }
                else if (saveResult.state === "INCOMPLETE") {
                    console.log("User is offline, device doesn't support drafts.");
                }
                else if (saveResult.state === "ERROR") {
                    console.log('Problem saving contact, error: ' +
                                 JSON.stringify(saveResult.error));
                }
                else {
                    console.log('Unknown problem, state: ' + saveResult.state +
                                ', error: ' + JSON.stringify(saveResult.error));
                }
            });
        }
    },

    doReset: function(component, event, helper) {
        //$A.get("e.force:closeQuickAction").fire();
        helper.openNewContact(component);
    },
})

createContactByLDSHelper.js | to create a blank form and validation for the contact record

({
    
    openNewContact: function(component){
        component.find("contactRecordCreatorId").getNewRecord(
            "Contact", // objectApiName
            null, // recordTypeId
            false, // skip cache?
            $A.getCallback(function() {
                var rec = component.get("v.newContact");
                var error = component.get("v.newContactError");
                if(error || (rec === null)) {
                    console.log("Error initializing record template: " + error);
                }
                else {
                    console.log("Record template initialized: " + rec.sobjectType);
                }
            })
        );
    },


    validateContactForm: function(component) {
        var validContact = true;
        var allValid = component.find('contactField').reduce(function (validFields, inputCmp) {
            inputCmp.showHelpMessageIfInvalid();
            return validFields && inputCmp.get('v.validity').valid;
        }, true);

        if (allValid) {
            var account = component.get("v.account");
            if($A.util.isEmpty(account)) {
                validContact = false;
                console.log("Quick action context doesn't have a valid account.");
            }
        	return(validContact);
            
        }  
	}
       
})

createContactByLDS.design | to define an input attribute for this component

<design:component >
	<design:attribute name="recordId" label="Current Record Id"/>
</design:component>

Step 2: Create a flow where you will refer this Lightning Component. Just drag the Screen element in the Cloud Flow Designer and Select Lightning Component from “Add a Field” tab and set the input attribute named “recordId” of the Lightning Component. Save the flow named “Create Contact by Lightning Component” and activate it.

Step 3: Now, need to add the Flow in Lightning Record Page of Account. So, just open any account record and click “Edit Page” from Settings on the page and drag the “flow” into the record page. Now, select the flow name in the Lightning Record Page and select “Pass record ID into this variable” to send the record Id from Flow to Lightning Component.

Results

Steps to Remember

1. To refer any Lightning Component into the Flow, you must implement “lightning:availableForFlowScreens” at the component level.
2. If any attributes need to send to Lightning component from Flow, you have to define the design of Lightning Component just like

<design:component >
	<design:attribute name="recordId" label="Current Record Id"/>
</design:component>

3. When you will set the Lightning Component, you must set the input attribute of the Lightning Component.
4. When you will add the Flow in Lightning Record Page, do not forget to select “Pass record ID into this variable”, if needs to send record Id to Lightning Component via Flow.

3,359 total views, 3 views today

Call Flow from Lightning Component

Call Flow from Lightning Component

In this section, we will call a Flow from a Lightning Component. Same Assignment: Create a Contact by Flow calling from Lightning Component.

Step 1: Create a flow from Cloud Flow Designer. Already, we have created the flow in the last session. If you have missed out, Please click on the link to open the last session: Contact Creation Flow.

Step 2: Create a Lightning Component bundle named “createContactfromFlow“.

createContactfromFlow.cmp | calling a Flow from Lightning Component

<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId">	
    
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    
    <lightning:card >
    	<lightning:flow aura:id="createContactFlowId" onstatuschange="{!c.handleStatusChange}"/>
    </lightning:card>
</aura:component>

createContactfromFlowController.js | to start flow with input parameters

({
	doInit : function(component, event, helper) {
		var createContactFlowId = component.find("createContactFlowId");
        var inputVariables = [
            {
                name:"accountId",
                type:"String",
                value:component.get("v.recordId")
            }
        ];
        
        createContactFlowId.startFlow("Contact_Creation_Flow", inputVariables);
	},

    handleStatusChange : function(component, event, helper) {
        if(event.getParam("status") === "FINISHED") {
         /*var outputVariables = event.getParam("outputVariables");
          var outputVar;
          for(var i = 0; i < outputVariables.length; i++) {
             outputVar = outputVariables[i];
             if(outputVar.name === "contactId") {
                var urlEvent = $A.get("e.force:navigateToSObject");
                urlEvent.setParams({
                   "recordId": outputVar.value,
                   "isredirect": "true"
                });
                urlEvent.fire();
             }
          }*/
          $A.get('e.force:refreshView').fire();

       }
    }
})

Clarification

doInit: Initialize and starting the flow by aura:id. Now, we have the Input variable/attribute named “accountId” in the Flow. So, we need to send the current Account record Id to this flow input variable. Please check the syntax createContactFlowId.startFlow(“Contact_Creation_Flow”, inputVariables); “Contact_Creation_Flowis the API Name of the flow.

handleStatusChange: Salesforce has provided the functionality on flow called “onstatuschange” on lightning:flow. When the Status of flow has been changed, at that point of time respective function will be invoked.Here, the function’s name is “handleStatusChange”. We are doing refresh the related list of the current Account, when Status of the flow has been changed to “FINISHED“. You can redirect to the created record’s detail page. This code is commented out. You can check.

Step 3: Please place this Lightning Component in the Lightning Record Page of the Account record.

6,105 total views, 4 views today

Flow distribution for Lightning Record Page

Flow distribution for Lightning Record Page

In this section, we will learn how to refer flow in Lightning Record Page. We will create a contact record from an account by flow placing in account record page in Lightning Experience.

Basic Understanding on Contact Creation Flow by Cloud Flow Designer


 

Step 1: Please open Cloud Flow Designer from Set up screen(“search with ‘Flows’ keyword in the search box of left panel” ).

Step 2: Please create a Flow with all the necessary information. Please mark the respective element as Starter by green signal. Here, Record Lookup is our starting element of the flow.

Step 3: After creation, please activate the flow. Flow has the versioning system. You can create multiple versions for a flow, but only one version can be active at a time. Please find the screenshot of the active flow named “Contact Creation”. 

Record Lookup:  It looks us the current account record with respect to account record Id and returns the Account Name.
Contact Inputs Screen: It is the layout of the fields which are applicable for contact creation.
Record Create: It allows to run the DML statement means you can insert the Contact record by using this element.
Error Handling Screen: We can customize the error handling by Flow Fault Message.
Thank You Screen: It will display Thank You message after creation of Contact.

Step 4: Need to place this flow in Lightning Record Page of account. So, Please edit the Lightning Record Page and drag the flow into the respective section of this record page.

Step 5: We have created an input variable named “accountId” in the flow to take the current Account Record Id. Now, we have to pass the Account Record Id to “accountId” variable mentioned in the flow. So, after dragging the flow in the Lightning Record Page, Please check this checkbox “Pass Record ID into this variable”.

Remember, when you will drag this flow in the Lightning Record Page, you will not see the flow immediately because Flow doesn’t run in a canvas. After saving the Lightning Record Page with Flow, you can see the flow on the Account Record.

 

2,773 total views, 3 views today

How to use global value providers?

Global Value Providers: Salesforce has provided some global value providers to be used in Lightning Component expressions. So, you don’t need to write your own methods to take the Browser Information, Custom Labels etc..

Global Value ProviderFeatureSyntax
$LabelYou can access custom labels using this global value provider in your Lightning Component Bundle.in component/app(.cmp/.app) file
{!$Label.c.labelName}

in controller/helper.js/ any js file
$A.get("$Label.c.labelName")

if your organization has a namespace, please replace "c" with the namespace just like
{!$Label.namespace.labelName}  -- optional, you can refer "c" or "namespace" in cmp files.
$A.get("$Label.namespace.labelName") -- required to replace the namespace in JS files.
$Browser It provides the hardware and operating system of the browser accessing the application.in component/app(.cmp/.app) file

{!$Browser.isTablet}
{!$Browser.isPhone}
{!$Browser.isAndroid}
{!$Browser.isIOS}
{!$Browser.isWindowsPhone}
{!$Browser.isIPad}
{!$Browser.formFactor} => returns DESKTOP/PHONE/TABLET as enum value

in controller/helper.js/any js file

$A.get("$Browser.isIOS");
$ResourceIt is used to reference images, script files, style sheets and other files fro Static Resource$Resource is not downloaded until Lightning Component framework is loaded on the client side. To make sure, all files are loaded used rerender function.
in component/app(.cmp/.app) for taking image files
< !-- Standalone Image Files -- >
< img src="{!$Resource.imageName}" />
< img src="{!$Resource.namespace__imageName}" />

< !-- Archived Image Files -- >
< img src="{!$Resource.archivedImageFile + '/images/image1.jpg'}" />
< img src="{!$Resource.namespace__archivedImageFile + '/images/image1.jpg'}" />

in component/app(.cmp/.app) for taking Styles and Scripts files
scripts="{!$Resource.archivedScriptFile + '/samplescript.js'}"
afterScriptsLoaded="{!c.scriptsLoaded}" />

in controller/helper.js/any js file
$A.get('$Resource.archivedImageFile ') + '/images/image1.jpg'

Multiple files loaded into component at a same time. Need to use 'join' statement
scripts="{!join(' ,' , $Resource.archivedStyleFile + '/style1.js',
$Resource.archivedStyleFile + '/style2.js')}"

Manage Package Consideration
Static Resource Files are not automatically added into the package if it is referenced in JS files. You need to include the Static Resource Files manually into the package component list prior to upload.
$LocaleIt returns current user's locale information.in component/app(.cmp/.app) file
{!$Locale.language}

in controller/helper.js/any js file
$A.get("$Locale.language");

Some Important Locale Attributes

country                           returns ISO 3166 Code                                     "US", "GB"
currency                         returns Symbol                                                    "$"
currencyCode              returns ISO 4217 Code                                      "USD"
language                        returns language Code                                     "en"
timeZone                       returns timezone Id                                            "America/Los_Angeles"
dateFormat                   returns dateformat                                             "MMM d, yyyy"
timeFormat                   returns timeformat                                             "h:mm:ss a"

9,483 total views, 15 views today

Lightning Component Rendering Lifecycle – How to use render.js file?

What is Document Object Modal(DOM)?
DOM is nothing but a programming API for HTML and XML documents. DOM is the logical structure(i.e., tree) of the documents.

Now question is, how can we update the DOM structure created by pre-defined  Lightning Component?
Yes, we can manage and update the pre-defined DOM Structure by Custom Rendering functionality provided by Lightning Component Framework in Salesforce.

Salesforce Lightning Component Framework has provided us four phases of Rendering.

render()afterRender()rerender()unrender()
To override the base render() function after component initialization.To update the DOM tree after inserted DOM elements by render() function.This is triggered due to anything change to the components. It is called by the framework when a component is being destroyed.
Need to call superRender() function.Need to call superAfterRender() function.Need to call superRerender() function.Need to call superUnrender() function.
It returns value (DOM or NULL).Generally, it does not return a value.Generally, it does not return a value.Generally, it does not return a value.
event is not supported as a function parameter.event is not supported as a function parameter.event is not supported as a function parameter.event is not supported as a function parameter.
anything needs to be changed during default rendering.If DML operation is needed during component initialization, put logic in afterRender() function instaed of writing in init() function.It is triggered if anything is changed to the components just like button disable after clicked the button to show some results.If any component is not displayed due to aura:if condition is not satisfied or component is not displayed conditionally, at that point unrender() function of this component will be fired.
render : function(component, helper) {
var ret = this.superRender();
// custom rendering logic here
return ret;
}
afterRender: function (component, helper) {
this.superAfterRender();
// interact with the latest DOM tree made by render() function
}
rerender : function(component, helper){
this.superRerender();
// custom rerendering logic here
}
unrender: function (component, helper) {
this.superUnrender();
// custom unrendering logic here
}

Diagram of Rendering Lifecycle 

We have to create three lightning components to learning this article.

  1. defaultLightningPanel
  2. showContacts [In this learning, we will not describe how to write “showContacts” component. You can write this Lightning Component using lightning:dataTable]
  3. renderingLifecycle

Below images depicts our assignments: [At the time of opening the table, User can see the Welcome message and when User will click on “Show My Contacts” button, user will see all the  contacts created by that user.]

 

 

 

Step 1:  Create a Lightning Component Bundle named “defaultLightningPanel“.

defaultLightningPanel.cmp | to show the default message in the contacts panel.

<aura:component>
         <aura:attribute name="displayMessage" type="String"/>
         <lightning:layout multiplerows="true" verticalalign="center">
              <lightning:layoutItem padding="around-small" size="12">
                <div class="slds-align_absolute-center">
                  <label class="slds-text-color_inverse">{!v.displayMessage}</label>
                </div>
              </lightning:layoutItem>
          </lightning:layout>
</aura:component>

Step 2: we need to focus on defaultLightningPanelRenderer.js file to understand unrender functionality.

defaultLightningPanelRenderer.js | when this component is destroyed, unrender() function will be invoked. Later we will discuss in detail.

({
	unrender : function(component, helper) {
        this.superUnrender();
        console.log("---entry in unrender---"); 
        component.set("v.displayMessage","My Contact(s)");
        
        
    },
})

Step 3: Create a Lightning Component named “showContacts” in where you can pass the logged in User’s Id and returns the list of Contacts with respect to User Id. [In this learning, we will not describe how to write “showContacts” component. You can write this Lightning Component using lightning:dataTable]

Step 4: Create a Lightning Component Bundle named “renderingLifecycle“.

renderingLifecycle.cmp | to show the Contacts Panel

<aura:component implements="flexipage:availableForAllPageTypes" controller="RenderingLifecycleController">

            <aura:attribute name="welcomeMsg" type="String" description="to store the Welcome Message"/>
            <aura:attribute name="userName" type="String" description="to store the name of the logged in user"/>
            <aura:attribute name="userId" type="String" description="to store the name of the logged in user"/>
            <aura:attribute name="headerLine" type="String" description="to show the header of Welcome Panel"/>
            <aura:attribute name="contactObj" type="Object" description="define the instance of Contact object"/>              
            <aura:attribute name="contactColumns" type="List" description="define the columns to visible in lightning dataTable"/>
            <aura:attribute name="showContacts" type="Boolean" description="to control the show contacts panel"/>
            <aura:attribute name="defaultMessage" type="String" default="NO CONTACT(S)" description="default message"/>

            <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

            <lightning:card title="">
               <aura:set attribute="title">
                    <lightning:icon iconName="standard:avatar" size="small"/>
                    <span style="font-size: 1rem" class="slds-m-left_small"> {!v.headerLine}</span>
               </aura:set>
               <aura:set attribute="actions">
                      <lightning:button label="Show My Contacts" onclick="{!c.showMyContacts}"
                                        aura:id="showContactsBtnId"/>
               </aura:set>
               <aura:if isTrue="{!v.showContacts}">
                   <div style="padding:0.5rem;background: rgb(22, 50, 92);">
                        <label class="slds-text-color_inverse">{!v.defaultMessage}</label>
                   </div>
                   <c:showContacts userId="{!v.userId}"/>
                   <aura:set attribute="else">
                        <c:defaultLightningPanel displayMessage="{!v.defaultMessage}"/>
                   </aura:set>
                </aura:if>
             </lightning:card>
</aura:component>

Step 5: Update the controller.js file.

renderingLifecycleController.js |  doInit() function is invoked ans set the value of welcomeMsg attribute as “Welcome”.

When you will press “Show My Contacts” button, we have set the Boolean variable as “showContacts” as true to open the Contacts Panel with Contact records.

({
	doInit : function(component, event, helper) {
		console.log("---entry in init---");
                component.set("v.welcomeMsg", "Welcome ");
	},

	showMyContacts : function(component, event, helper){
               component.set("v.showContacts", true);
	}
})

Step 6: Update the helper.js file

renderingLifeCycleHelper.js | to show the contact records with respect to logged in User Id

({
	performShowingLoggedInUserDetails : function(component) {

		var action = component.get("c.getloggedinuserDetails");
		this.setShowingLoggedInUserDetails(component, action);
		$A.enqueueAction(action);
	},

	setShowingLoggedInUserDetails : function(component, action){

		action.setCallback(this, function(response){
			this.handleShowingLoggedInUserDetails(component, response);
		});
	},

	handleShowingLoggedInUserDetails : function(component, response){

		var responseState = response.getState();
		var responseError = response.getError();
		var responseValue = response.getReturnValue();

		switch(responseState){

			default: break;
			case 'NEW': break;
			case 'RUNNING': break;

			case 'SUCCESS':
					if(typeof responseValue != undefined &amp;amp;&amp;amp; responseValue.length &amp;gt; 0){
						component.set("v.userId", responseValue[0].Id);
						component.set("v.userName", responseValue[0].Name);
					}

					component.set ("v.headerLine", component.get("v.welcomeMsg") + component.get("v.userName"));

			case 'INCOMPLETE': break;
			case 'ERROR': 
				console.log('Response Error--&amp;gt;'+JSON.stringify(responseError));
				break;

		}
		 
	},


	
})

Step 7: update the render.js file

renderingLifecycleRenderer.js 

render() function is  called after completion of doInit() function by component.  By doInit() function, “welcomeMsg” attribute has been set to “Welcome“, now by render() function we have appended the value of “welcomeMsg” attribute as “To“.So, final value of “welcomeMsg” attribute has been set to “Welcome To” after completion of render() function.

After execution of render() function, afterRender() function will be invoked and the respective helper function “performShowingLoggedInUserDetails()” will be called to execute the server action to fetch the logged in User Name and concatenate the string with User Name, just like “Welcome To Santanu Pal“.

So, whenever the value of “welcomeMsg” attribute has been changed, the rerender() function will be triggered. For learning purpose, we will disable the button when “Show My Contacts” button has been pressed. In this case, the button’s visibility is controlled by a Boolean variable named “showContacts”.

 

({
	render : function(component, helper) {
        console.log("---entry in render---");
    	var ret = this.superRender();
    	component.set("v.welcomeMsg",component.get("v.welcomeMsg")+"To ");
    	return ret;
	},

    afterRender : function(component, helper){
        console.log("---entry in afterRender---");
        this.superAfterRender();
        helper.performShowingLoggedInUserDetails(component);
    },

    rerender : function(component, helper){
        console.log("---entry in rerender---");        
        this.superRerender();
        if(component.get("v.showContacts")){
            var showContactcsBtnId = component.find("showContactsBtnId");
            showContactcsBtnId.set("v.disabled", true);
        }
    },

	
})

Step 8: Please call the “renderingLifecyle” component from Lightning Application.

Console Statements
As per the Rendering Lifecycle, if we want to print console.log, this log will be generated in such a way:

At the time of loading the Lightning Application

—entry in init—
—entry in render—
—entry in afterRender—
—entry in rerender—

The last rerender function() is called because at the time of running render() function, the value of “welcomeMsg” attribute has been changed.

After clicked “Show My Contacts” button.

—entry in rerender—
—entry in unrender—
—entry in rerender—

unrender() function of defaultLightningPanel component is invoked when this component is destroyed from “renderingLifeCycle” component. If you see this component this panel will be invoked when “showContacts” is false(by default nature). Now, when we clicked “Show My Contacts” button”, “showContacts” boolean variable has been set to true and the “defaultLightningPanel” Lightning Component is hidden/destroyed and “showContacts” component will be opened.  As “defaultLightningPanel” Lightning Component is hidden/destroyed, the unrender() function of this component will be trigerred.

52,730 total views, 3 views today

Lightning Component – Server Side Implementation in a Smart Way

For this training purpose, we are showing the contact records with respect to an account on the Account Lightning Record Page. We are using aura:iteration with html table for training purpose. Please use lightning base components such as lightning:dataTable in future.

Step 1: Create the Apex Class named “ShowContactsController”

ShowContactsController.apexc | To return all the associated Contact Records

/* @name: ShowContactsController 
   @description: return the Contact Records*/

public class ShowContactsController {
    
    @AuraEnabled
    public static List<Contact> getContactRecords(String accountId){
        
        List<Contact> contactList = [SELECT Id, Name, Account.Name, Owner.name, LastModifiedDate, CreatedBy.Name FROM Contact WHERE Account.Id =: accountId ORDER BY LastModifiedDate Desc];
        if(contactList <> NULL && contactList.size()>0)
        	return contactList;
        else
            return NULL;
    }

}
  • Lightning Components will understand only methods with @AuraEnabled annotation in Apex Class.
  • Apex Methods must be static and access specifier should be public or  global for Lightning Component’s communication.

Step 2:  Create a lightning component bundle named “showContacts”.

showContacts.cmp | to show the associated Contact Records [you can use lightning:dataTable]

<!-- @name: showContacts
 	 @description: to show the contact records with respect to Account-->

<aura:component implements="flexipage:availableforAllPageTypes,force:hasRecordId" controller="ShowContactsController">
    
    <aura:attribute name="contactList" type="List" description="contains Contact records"/>    
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    
    <table class="slds-table slds-table_fixed-layout slds-table_bordered">
        <thead>
            <tr class="slds-text-heading--label">                  
                <th scope="col" class="slds-cell-wrap" title="Name">
                    <div class="slds-truncate">Name</div>                      
                </th>
                <!--<th scope="col" class="slds-cell-wrap" title="Account Name">
                    <div class="slds-truncate">Account Name</div>                      
                </th>-->
                <th scope="col" class="slds-cell-wrap" title="Owner">
                    <div class="slds-truncate">Owner</div>                      
                </th>
                <th scope="col" class="slds-cell-wrap" title="Last Modified Date">
                    <div class="slds-truncate">Last Modified Date</div>                      
                </th>
                <th scope="col" class="slds-cell-wrap" title="Created By">
                    <div class="slds-truncate">Created By</div>                      
                </th>
            </tr>
        </thead> 
        <tbody>
            <aura:iteration items="{!v.contactList}" var="con">
                <tr>
                    <td class="slds-truncate" title="{!con.Name}">
                        <lightning:formattedText value="{!con.Name}"/>            
                    </td> 
                    <!--<td class="slds-truncate" title="{!con.Account.Name}">
                        <lightning:formattedText value="{!con.Account.Name}"/>            
                    </td>-->
                    <td class="slds-truncate" title="{!con.Owner.Name}">
                        <lightning:formattedText value="{!con.Owner.Name}"/>            
                    </td> 
                    <td class="slds-truncate" title="{!con.LastModifiedDate}">
                        <lightning:formattedDateTime value="{!con.LastModifiedDate}" year="2-digit" month="short" day="2-digit"/>            
                    </td> 
                    <td class="slds-truncate" title="{!con.CreatedBy.Name}">
                        <lightning:formattedText value="{!con.CreatedBy.Name}"/>            
                    </td> 
                </tr>
            </aura:iteration>
        </tbody>
    </table>   
</aura:component>

showContactsController.js | calling the helper function

/*controller.js*/
({
	doInit : function(component, event, helper) {
		helper.performShowingContacts(component, event);
	}
})

showContactsHelper.js | calling the Server Class and get the response from Server and set the respective return value

/*helper.js*/
({
    performShowingContacts : function(component) {
		var action = component.get("c.getContactRecords");
		this.setupPerformShowingContactsAction(component, action);
		$A.enqueueAction(action);
    },
    
    setupPerformShowingContactsAction : function(component, action) { 

		action.setParams({
			"accountId":component.get("v.recordId")
		});

		action.setCallback(this, function(response){
        	this.handlePerformShowingContactsResultsCallBack(component, response)
        });	
    },
    
    handlePerformShowingContactsResultsCallBack : function(component, response) {

		var responseState = response.getState();
		var responseError = response.getError();
		var responseValue = response.getReturnValue();

		switch(responseState){

			default: break;
			case 'NEW': break;
			case 'RUNNING': break;

			case 'SUCCESS':
                
                if(!$A.util.isEmpty(responseValue))
                    component.set("v.contactList", responseValue);
                
                break;
                
            case 'INCOMPLETE': break;
			case 'ERROR': 
				console.log('Response Error-->'+JSON.stringify(responseError));
				break;
        }
        
    }
    
    
})


performShowingContacts:
This is responsible to call the specific method of Apex Class [Method Name: getContactRecords,  Class: ShowContactsController].
You can notice that we are calling the method by this syntax:  component.get(“c.getContactRecords”); And, $A.enqueueAction(action) is responsible to add the Server Side Action to the processing queue. Before going to this, the respective method named “setupPerformShowingContactsAction” is called.

setupPerformShowingContactsAction: This method is responsible to set the parameters in the respective method of the Apex Class.

      • In Apex Class: public static List<Contact> getContactRecords(String accountId)
      • In Helper: action.setParams({ “accountId“:component.get(“v.recordId”) });   // component.get(“v.recordId”) will return the current Account Record Id.

handlePerformShowingContactsResultsCallBack: action.setCallback() sets a callback action that is invoked after completion of server side actions. In this, method you will get the response state, response value as well as response errors.

There will be 5 types of responses.

      1. NEW – The action is created, but there is no progress yet
      2. RUNNING – The action is in progress.
      3. SUCCESS – The Action has been executed successfully.
      4. ERROR – The Server returned the error to Lightning Component
      5. INCOMPLETE – Component has not received the response. The Server might be down or Client is in offline mode.

After executed successfully, we have set the responseValue to contactList into the component. After that, component will iterate the contact list and will show the contact records.

Step 3: Place this Lightning Component into the Account Record Page.

 

Notes

  1. Calling server-side actions from Lightning Component are not counted against your organization’s API limits. However, all the Governor Limits in the Apex Class retain.
  2. The request payload limit of action.setParams() is 4 MB yet. So, please check the feasibility of  parameters in your apex class and js files of a Lightning Component.
  3. Always try to put the unique name of client-side and server-side actions in a component. For example, if we will write the function with same name such as “getContactRecords” in controller.js, it will call the function “getContactRecords” in controller.js instead of Calling Method of a Apex Class. May be, for that you can get error as in “unexpected execution process in infinite loop“.

 

11,358 total views, 9 views today

Advanced Event Communication – Application Event Propagation

Event Propagation is a way of communication in your application. Following are the phases supported in event communication

1. Capture Phase: The event is captured from application root to the source component. [top to bottom].

2. Bubble Phase: The event is bubbled up from source component to the application root. [bottom to top]

 

Application Event has one more phase called “Default” phase

3. Default  Phase: It respects framework’s default handling behavior.

Source Component [Where event is triggered]button

Application RootWindow

confused? Let’s start to discuss in detail

 

 

Before going to discuss, we need to understand the basic ideas about the component creation.

  1. Declarative Component: A component which is referred from outermost component which is the owner of the Containment Hierarchy.
  2. Programmatic Component:  A Component is invoked from the component by $A.createComponent() in js file.
  3. Container: We will call the component as container where {!v.body} or Aura.Component[] attributes are declared, means containing other component, not referring other component.
  4. Owner of Containment Hierarchy: A component which will create or refer to other component, not containing other component by {!v.body} tag or Aura.Component[] facet attribute. A component owner is  the component to responsible for creation of other component.

Application Event – It propagates to every owner in the hierarchy.

Default: Default Phase: If components are disconnected and want to communicate between the components, you have to use the Application Event. At that point, event phase should be default phase.  All component will catch the application event in same time. In this case, we can not use the bubble phase or capture phase.

If the components are connected and if we use Application Event, then we can use Bubble or Capture phase.

Disconnected Components

 

Component 1, Component 2, Component 3 and Component 4 are disconnected. Component 4 has the button named “Check Default Phase” by which the Application Event is registered and transmitted. Due to default behavior of handling components or default phase, all components or receivers will catch the event at same time. You can check the Graphical View image.

Hence, the result would be

I am the Receiver 1
I am the Receiver 2
I am the Receiver 3

In this component structure, you can not use the event Bubble Phase or Capture Phase.

Connected Components with Application Event Bubble Phase

In this component structure, three types of phases are allowed such as Default Phase, Bubble Phase and Capture Phase, because now these components are connected.  Now, we will discuss about Bubble Phase.

To run the Bubble Phase you have to mention phase= “bubble” in aura:handler tag of Component 1, Component 2 as well as Component 3. Just like

  <aura:handler event="c:applicationEvent" action="{!c.checkResponse}" phase="bubble"/> 

Due to Bubble Phase, application event will propagate from bottom to top or from Source Component[button] to root component[Component 1]. Component 3 and Component 1 will catch the event as they are the owner of containment hierarchy. Component 2 is not the owner of Containment Hierarchy, so it will not be able to do cat ch the event as well as not able to print the message.

Hence, the result would be

I am the Grand Child Component
I am the Parent Component

Connected Components with Application Event Capture Phase

To run the Capture Phase you have to mention phase= “capture” in aura:handler tag of Component 1, Component 2 as well as Component 3. Just like

  <aura:handler event="c:applicationEvent" action="{!c.checkResponse}" phase="capture"/> 

Due to Capture Phase, application event will propagate from top to bottom or from root component[Component 1] to Source Component[button]. Component 1 and Component 3 will catch the event as they are the owner of containment hierarchy. Component 2 is not the owner of Containment Hierarchy, so it will not be able to do cat ch the event as well as not able to print the message.

Hence, the result would be

I am the Parent Component
I am the Grand Child Component

You can check the Component Event Propagation about detailing of Capture and Bubble Phase

Sample Code Snippet for Disconnected Components with Default Phase

component 1 [Receiver 1]

<aura:component>
 <aura:handler event="c:applicationEvent" action="{!c.checkResponse}"/>
</aura:component>

component 2 [Receiver 2] 

<aura:component>
 <aura:handler event="c:applicationEvent" action="{!c.checkResponse}"/>
</aura:component>

component 3 [Receiver 3]

<aura:component>
 <aura:handler event="c:applicationEvent" action="{!c.checkResponse}"/>
</aura:component>

component 4 [button is here] 

<aura:component>
 <aura:registerEvent name="applicationEvent" type="c:applicationEvent"/>
 <lightning: button label="Check Default Phase" action="{!c.fireEvent}"/>
</aura:component>

LearningLightning.app | All components will be run from this application

<aura:component>
  <c:component 1/>
  <c:component 2/>
  <c:component 3/>
  <c:component 4/>
</aura:component>

Component 1, Component 2, Component 3 and Component 4 are disconnected. Component 4 has the button named “Check Default Phase” by which the Application Event is registered and transmitted. Due to default behavior of handling components or default phase, all components or receivers will catch the event at same time.

Hence, the result would be

I am the Receiver 1
I am the Receiver 2
I am the Receiver 3

Asynchronous Code Execution: You can pause or resume the event by the respective methods event.pause() or event.resume() in js files. These tags are needed to take the decision based on user input and response from asynchronous code and for certain conditions, we have to pause the event and after satisfying the criteria, again we can resume the event. By this, we can manage the flow-control mechanism for asynchronous code.

Stop Event Propagation: You can stop the event propagation by the respective method event.stopPropagation().

Q. If you want to print all the messages from all the connected components, what will you do?

IncludeFacets in Container Component: If you want to catch the event through container component, you need to write the attribute as “includeFacets=true” in aura:handler tag of a container component. In our example, we have a container component as “Component 2”. If we will include the attribute as “includeFacets=true“, it will be able to handle the event and print the message.

component 2 [Child Component in the Connected Components]

<aura:component>
  <aura:handler name="componentEvent" event="c:componentEvent" action="{!c.checkResponse}" includeFacets="true"/>
     {!v.body}
</aura:component>

Results in Bubble Phase using “includeFacets=true”  in Component 2

I am the Grand Child Component
I am the Child Component
I am the Parent Component

Results in Capture Phase using “includeFacets=true”  in Component 2

I am the Parent Component
I am the Child Component
I am the Grand Child Component

Q. If you want to print all the messages from all the disconnected components, what will you do?

Nothing to do. By default, all the messages will be printed from all the disconnected components due to “Default” phase behavior inclusion of Application Event.

Best Practice: If components are connected, use Component Event instead of Application Event. If components are disconnected, you should use the Application Event.

                                                                                        Thank you for concentrating a long time  session

12,806 total views, 3 views today

Advanced Event Communication – Component Event Propagation

Event Propagation is a way of communication in your application.  Following are the phases supported in event communication

1. Capture Phase:  The event is captured from application root to the source component. [top to bottom].

2. Bubble Phase:  The event is bubbled up from source component to the application root. [bottom to top]

Source Component [Where event is triggered]button

Application Root – Window

 

 

 

 

 

 

Before going to discuss, we need to understand the basic ideas about the component creation.

  1. Declarative Component: A component which is referred from outermost component which is the owner of the Containment Hierarchy.
  2. Programmatic Component:  A Component is invoked from the component by $A.createComponent() in js file.
  3. Container: We will call the component as container where {!v.body} or Aura.Component[] attributes are declared, means containing other component, not referring other component.
  4. Owner of Containment Hierarchy: A component which will create or refer to other component, not containing other component by {!v.body} tag or Aura.Component[] facet attribute. A component owner is  the component to responsible for creation of other component.

Component Event – It propagates to every owner in the hierarchy.

Default: Bubble Phase : Event will be passed from bottom to top means from source component to application root.

Component 1 is calling Component 2 which contains Component 3 and Component 3 is calling Component 4 where only the button “Check Bubble Phase” resides.  When you will click the button in Component 4, component event is registered in component 4[Source Component] and due to bubble phase[bottom to top] at first Component 3 will catch the event after that Component 1 will catch the event. But, Component 2 will not be able to catch the event because Component 2 is the container component and it is not the owner of the containment hierarchy means it is not exactly calling component 3, it is containing Component 3 in its body and also it is not the outermost component. Only Component 1[Parent Component] and  Component 3[Grand Child Component] are the owner of containment hierarchy, so they will be able to catch the component event and print the message.

Sequence of Events [When you will click the button “Check Bubble Phase“]

  1. Component Event is registered in Component 4.  This event will pass from bottom to top, just like bubble.
  2. Component 3 prints the message through its handler. Component 3 is the owner of Containment Hierarchy.
  3. Component 2  has the handler of this event, but it is the container component and not the owner of Containment Hierarchy. So, It will not be able to catch the event.
  4. Component 1 is the parent component and outer most component as well as owner of the Containment Hierarchy. Hence, it prints the message through its handler.

Hence, the result would be

I am the Grand Child Component
I am the Parent Component

Sample Code Snippet for understanding

component 1 [Parent Component]

<aura:component>
  <aura:handler name="componentEvent" event="c:componentEvent" action="{!c.checkResponse}"/>
  <c:component 2>
     <c:component 3>
  </c:component 2>
</aura:component>

component 2 [Child Component] | here {!v.body} is defined to contain the component 3

<aura:component>
  <aura:handler name="componentEvent" event="c:componentEvent" action="{!c.checkResponse}"/>
  {!v.body}
</aura:component>

component 3 [Grand Child Component]

<aura:component>
  <aura:handler name="componentEvent" event="c:componentEvent" action="{!c.checkResponse}"/>
  <c:component 4/>
</aura:component>

component 4 [button is here] | register the component event

<aura:component>
  <aura:registerEvent name="componentEvent" type="c:componentEvent"/>
  <lightning: button label="Check Bubble Phase" action="{!c.fireEvent}"/>
</aura:component>

Respective handlers for Component 1, Component 2 and Component 3 are the same as Component Event handler syntax.

Capture Phase: Event will be captured from top to bottom means from application root to source component.

We will take the same component structure to describe the Capture Phase.

 

 

To run the Capture Phase you have to mention phase=”capture” in  aura:handler tag of Component 1, Component 2 as well as Component 3. Just like

   <aura:handler name="componentEvent" event="c:componentEvent" action="{!c.checkResponse}" phase="capture"/>

When you will click the button in Component 4, component event is registered in component 4[Source Component] and due to capture phase[top to bottom] at first Component 1 will catch the event after that Component 3 will catch the event. But, Component 2 will not be able to catch the event because of the same reason as Component 2 is the container component and it is not the owner of the containment hierarchy.

Sequence of Events [When you will click the button “Check Capture Phase“]

  1. Component Event is registered in Component 4.  This event will be captured from top to bottom.
  2. Component 1 prints the message through its handler. Component 1 is the owner of Containment Hierarchy.
  3. Component 2  has the handler of this event, but it is the container component and not the owner of Containment Hierarchy. So, It will not be able to catch the event.
  4. Component 3 is also owner of the Containment Hierarchy and will call the Component 4 to show the button “Check Capture Phase”. Hence, it prints the message through its handler.

Hence, the result would be

I am the Parent Component
I am the Grand Child Component

Asynchronous Code Execution: You can pause or resume the event by the respective methods event.pause() or event.resume() in js files. These tags are needed to take the decision based on user input and response from asynchronous code and for certain conditions, we have to pause the event and after satisfying the criteria, again we can resume the event. By this, we can manage the flow-control mechanism for asynchronous code.

Stop Event Propagation: You can stop the event propagation by the respective method event.stopPropagation().

Q. If you want to print all the messages from all the components, what will you do?

IncludeFacets in Container Component: If you want to catch the event through container component, you need to write the attribute as “includeFacets=true” in aura:handler tag of a container component. In our example, we have a container component as “Component 2”. If we will include the attribute as “includeFacets=true“, it will be able to handle the event and print the message.

component 2 [Child Component]

<aura:component>
  <aura:handler name="componentEvent" event="c:componentEvent" action="{!c.checkResponse}" includeFacets="true"/>
  {!v.body}
</aura:component>

Results in Bubble Phase using “includeFacets=true”  in Component 2

I am the Grand Child Component
I am the Child Component
I am the Parent Component

Results in Capture Phase using “includeFacets=true”  in Component 2

I am the Parent Component
I am the Child Component
I am the Grand Child Component

                                                               Thank you for concentrating a long time  session

4,439 total views, 1 views today

Events Communication in Lightning

Lightning Events are used to communicate to direct Lightning Components or indirect Lightning Components in Lightning Framework.

Component Event: This type of event can be fired from a Component and on other side, the component in the same hierarchy will handle/receive the event. Both components are correlated or coupled or directly connected.

Application Event: This type of event can be fired from a component and other component will receive/handle the event in the application. But, the components are not in the hierarchy model as well as components are not correlated or indirectly connected. You can refer this as Publish-Subscribe model.

Component Event Communication Rules:

1. Create Component Event(.evt) and declare the specific attributes as per business.
2. Register the Event into the notifier component where this event will be fired/triggered.
3. Receive the Event into the handler component where the value of Event attributes will be passed.
4. Both Notifier and Handler Components are in the same component hierarchy.

Let’s start with Component Event

Step 1: Create a Component Event named “componentEvent“.

componentEvent.evt | defines the component event

<aura:event type="COMPONENT" description="Component Event template">
   <aura:attribute name="message" type="String"/>
</aura:event>

Step 2: Create a notifier component bundle “notifier” where Event will be registered and fired.

notifier.cmp | register the component event


<aura:component>
      <!-- register Event -->
      <aura:registerEvent name="componentEvent" type="c:componentEvent"/>
      

<div class="slds-align_absolute-center slds-m-top_large">
         <lightning:button variant="brand" label="Submit (in notifier)" value="Trigger Event" onclick=" {!c.fireEvent}"/>
      </div>


</aura:component>

notifierController.js  | fired the component event

({
	fireEvent : function(component, event, helper) {
	    var componentEvent = component.getEvent("componentEvent");
            componentEvent.setParams({
                "message":"Event: ComponentEvent is fired." 
            });
            componentEvent.fire();	
	}
})

Step 3: Create a handler component bundle “handler” where the value of Event attributes will be passed.

handler.cmp | handler function is called

<aura:component> 
 <aura:attribute name="notificationMsg" type="String"/>
 <aura:handler name="componentEvent" event="c:componentEvent" action="{!c.receivesEvent}"/>
 <c:notifier/> 
 

<div class="slds-align_absolute-center slds-m-top_medium">
    <b>{!v.notificationMsg}</b> 
 </div>


</aura:component>  

handlerController.js | receives the triggered event

({
	receivesEvent : function(component, event, helper) {
	     var message = event.getParam("message");
             component.set("v.notificationMsg", message +' (in handler)');
        }
})

Step 4: Calling the handler from Lightning App named “LearnLightning“.

LearnLightning.app | To call the handler component from this application

<aura:application extends="force:slds>
    <c:handler/>
</aura:application>

Step 5: Results

From handler component, we are calling notifier component. So, both notifier and handler are in the same hierarchy.
We are registering the event into notifier and getting the result from handler component.

  • Submit button in notifier component

  • After clicked on Submit button, handler component receives the message from notifier by Component Event.

Application Event Communication Rules:

1. Create Application Event(.evt) and declare the specific attributes as per business.
2. Register the Event into the transmitter component where this event will be transmitted.
3. Receive the Event into the receiver component where the value of Event attributes will be passed.
4. Both Transmitter and Receiver component are not in same component hierarchy.

 

Let’s start with Application Event

Step 1: Create a Application Event named “applicationEvent“.

applicationEvent.evt | defines Application Event

<aura:event type="APPLICATION" description="Application Event template">
 <aura:attribute name="message" type="String"/>
</aura:event>

Step 2: Create a transmitter component bundle “transmitter” where Event will be registered and transmitted.

transmitter.cmp | register the application event


<aura:component>
       <!-- register Event -->
       <aura:registerEvent name="applicationEvent" type="c:applicationEvent"/>
       

<div class="slds-align_absolute-center slds-m-top_large">
          <lightning:button variant="brand" label="Submit (in transmitter)" value="Transmit Event" onclick=" {!c.transmitEvent}"/>
       </div>


</aura:component>

transmitterController.js  | transmitted the component event

({
	transmitEvent: function(component, event, helper) {
		var applicationEvent = $A.get("e.c:applicationEvent");
                applicationEvent.setParams({
                   "message":"Event: Application Event is transmitted." 
                });
                applicationEvent.fire();	
	}
})

Step 3: Create a receiver component bundle “receiver” where the value of Event attributes will be passed.

receiver.cmp | handler function is called

<aura:component>
    <aura:attribute name="notificationMsg" type="String"/>
    <aura:handler event="c:applicationEvent" action="{!c.receivesEvent}"/>
    

<div class="slds-align_absolute-center slds-m-top_large">
       <lightning:card title="Receiver">
          <b>{!v.notificationMsg}</b>
       </lightning:card>
    </div>


</aura:component>

receiverController.js | receives the transmitted event

({
	receivesEvent : function(component, event, helper) {
	     var message = event.getParam("message");
             component.set("v.notificationMsg", message);
        }
})

Step 4: Calling both transmitter and receiver components from Lightning App named “LearnLightning“.

LearnLightning.app

<aura:application extends="force:slds">
    <c:transmitter/>
    
    <c:receiver/>
</aura:application>

Step 5: Results

We are calling both components such as “transmitter” and “receiver” from the application. Both transmitter and receiver are not in the same hierarchy and they are disconnected in the application.

  •  Submit button is in transmitter component.  Receiver component is waiting for transmitted message from transmitter.
  • After clicked on Submit button, application event is transmitted. Receiver component is always checking that any request is coming or not from transmitter. When application event is received,  Receiver prints the message transmitted from transmitter.

3,838 total views, 3 views today

What is bound{! } expression and unbound{# } expression?

Bound Expression: {!v.attributeName}: Anything has been changed to the attribute in the Child Component affects the respective attribute in the Parent Component and vice-versa.
Unbound Expression: {#v.attributeName}: Anything has been changed to the attribute in the Child Component doesn’t affect the respective attribute in the Parent Component and vice-versa.

Following diagram depicts the use case of Bound Expression and Unbound Expression.

got the image. no 🙁 … Not an issue. Let’s we will start to discuss and again come to the this diagram

Let’s Start

Using Bound Expression
Step 1:Create a Child Component Bundle named “ChildComponent”

ChildComponent.cmp

<aura:component>
    <aura:attribute name="childAttr" type="String" description="defines child attribute"/>
    
<div class="slds-m-left--large">
          <b>In Child Component: </b>{!v.childAttr}     
          <lightning:button variant="brand" label="Change" onclick="{!c.changeChildAttr}" class="slds-m-left--small"/>
     </div>

</aura:component>

ChildComponentController.js | This method(“changeChildAttr”) is responsible to update the value of childAttr when “Change” button will be clicked.

({
	changeChildAttr : function(component, event, helper) {
		component.set("v.childAttr", "from Child Component.")
	}
})

Step 2: Create a Parent Component Bundle named “ParentComponent”.

ParentComponent.cmp

<aura:component>
    <aura:attribute name="parentAttr" type="String" default="from Parent Component."/>
    
<div class="slds-m-top--large">
        
<div class="slds-align_absolute-center">
    		<b>In Parent Component: </b> {!v.parentAttr}
        </div>

        
<div class="slds-m-top--large slds-m-left--large slds-align_absolute-center">
        	<c:ChildComponent childAttr="{!v.parentAttr}"/>
        </div>

     </div>

</aura:component>

Please notice that we have used Bound Expression {!v.parentAttr} whose default value “from Parent Component” will be passed to Child Component.

Step 3: As discussed earlier, we need to create the Lightning App(“LearnLightning”) to show the Result.

LearnLightning.app

<aura:application extends="force:slds">
    <c:ParentComponent />
</aura:application>

Step 4: Results

Result 1: Just run the app. Parent Component will pass the default value as “from Parent Component” to Child Component. So, both Component will display the same value on screen as “from Parent Component”.

Result 2: Just run the app. Now, you can click “Change” button on Child Component.So, the value of “childAttr” has been changed to “from Child Component”. Due to Bound Expression, it will be affected to the value of “parentAttr” in Parent Component. So, both Component will display the same value on screen as “from Child Component”.

Using Unbound Expression
Step 1:Same Child Component Bundle named “ChildComponent”

ChildComponent.cmp

<aura:component>
    <aura:attribute name="childAttr" type="String"/>
    
<div class="slds-m-left--large">
          <b>In Child Component: </b>{!v.childAttr}     
          <lightning:button variant="brand" label="Change" onclick="{!c.changeChildAttr}" class="slds-m-left--small"/>
    </div>

</aura:component>

ChildComponentController.js | This method(“changeChildAttr”) is responsible to update the value of childAttr when “Change” button will be clicked.

({
	changeChildAttr : function(component, event, helper) {
		component.set("v.childAttr", "from Child Component.")
	}
})

Step 2: Same Parent Component Bundle named “ParentComponent”.

ParentComponent.cmp

<aura:component>
    <aura:attribute name="parentAttr" type="String" default="from Parent Component."/>
    
<div class="slds-m-top--large">
        
<div class="slds-align_absolute-center">
    		<b>In Parent Component: </b>{!v.parentAttr}
        </div>

        
<div class="slds-m-top--large slds-m-left--large slds-align_absolute-center">
        	<c:ChildComponent childAttr="{#v.parentAttr}"/>
        </div>

     </div>

</aura:component>

Please notice that we have used Unbound Expression {#v.parentAttr} whose default value “from Parent Component” will be passed to Child Component. But, there will be no reflection from Child Component.

Step 3: Same Lightning App(“LearnLightning”) to show the Result.

LearnLightning.app

<application extends="force:slds">
    <c:ParentComponent />
</aura:application>

Step 4: Results

Result 1: Just run the app. Parent Component will pass the default value as “from Parent Component” to Child Component. So, both Component will display the same value on screen as “from Parent Component”.
reflection

Result 2: Just run the app. Now, you can click “Change” button on Child Component.So, the value of “childAttr” has been changed to “from Child Component”. Due to Unbound Expression, it will not change the value of “parentAttr” in Parent Component. So, Parent Component will display the value as “from Parent Component” and Child Component will display the value as “from Child Component”.bound result

Difference between Bound Expression and Unbound Expression

 
Bound Expression Unbound Expression
Using this type of expression, any change to the attribute of Child Component affects the attribute of the Parent Component and Vice-Versa.  Using this type of expression, any change to the attribute of Child Component doesn’t affect the attribute of the Parent Component and Vice-Versa.
It is bi-directional. It is one time uni-directional.
It hampers performance due to bi-directional flow. Please check component before using this type of expression.  It doesn’t hamper the performance due to  one time uni-directional flow , means there is no reflection from Child Component to Parent Component and Vice-Versa.
 It is difficult to study debug-log errors.  It is easy to track.
 It is applicable for Component Initialization as well as Data Binding.  It is not applicable for Component Initialization as well as in any controller/helper methods. It is only applicable for Data Binding.

 

Now Please go back to the first diagram of this post. Thanks 🙂

4,740 total views, 3 views today