lightning:fileUpload Example

lightning:fileUpload component provides an easy and integrated way for users to upload multiple files. The file uploader includes drag-and-drop functionality and filtering by file types. File uploads are always associated to a record, hence the recordId attribute is required. Uploaded files are available in Files Home under the Owned by Me filter and on the record’s Attachments related list on the record detail page. Although all file formats that are supported by Salesforce are allowed, you can restrict the file formats using the accept attribute. Here is the example code .

Lightnin Component 

<aura:component implements="force:hasRecordId,flexipage:availableForAllPageTypes" access="global" >
    <aura:attribute name="accept" type="List" default="['.jpg', '.jpeg']"/>
    <aura:attribute name="multiple" type="Boolean" default="true"/>
    <aura:attribute name="disabled" type="Boolean" default="false"/>
                    
    <lightning:fileUpload label="Add attachment" multiple="{!v.multiple}" 
                          accept="{!v.accept}" recordId="{!v.recordId}" 
                          onuploadfinished="{!c.handleUploadFinished}" />
    
</aura:component>

Controller 

({
    handleUploadFinished : function(component, event, helper) {
        var uploadedFiles = event.getParam("files");
        var documentId = uploadedFiles[0].documentId;
        var fileName = uploadedFiles[0].name;
        var toastEvent = $A.get("e.force:showToast");
        toastEvent.setParams({
            "title": "Success!",
            "message": "File "+fileName+" Uploaded successfully."
        });
        toastEvent.fire();
        
        $A.get('e.lightning:openFiles').fire({
            recordIds: [documentId]
        });
        
    }
})

 

Code walkthrough 

  1. event.getParam(“files”) returns a list of uploaded files with the properties name and documentId.name: The file name in the format filename.extension.documentId: The ContentDocument Id in the format 069XXXXXXXXXXXX.
        var uploadedFiles = event.getParam("files");
        var documentId = uploadedFiles[0].documentId;
        var fileName = uploadedFiles[0].name;

2. Below code will show the Toast on Successfully file upload

var toastEvent = $A.get("e.force:showToast");
        toastEvent.setParams({
            "title": "Success!",
            "message": "File "+fileName+" Uploaded successfully."
        });
        toastEvent.fire();

3.below code will open the file preview after file upload.

 $A.get('e.lightning:openFiles').fire({
            recordIds: [documentId]
        });

File Upload Limits

By default, you can upload up to 10 files simultaneously unless your Salesforce admin has changed that limit. The org limit for the number of files simultaneously uploaded is a maximum of 25 files and a minimum of 3 files. The maximum file size you can upload is 2 GB. In Communities, the file size limits and types allowed follow the settings determined by community file moderation. Guest user can’t add files.

Usage Considerations

This component is not supported in Lightning Out or standalone apps, and displays as a disabled input. Additionally, if the Don't allow HTML uploads as attachments or document records security setting is enabled for your organization, the file uploader cannot be used to upload files with the following file extensions: .htm, .html, .htt, .htx, .mhtm, .mhtml, .shtm, .shtml, .acgi, .svg.

Using jquery in lightning Components

In this blog post, I am going to explain how to use the jquery in the lightning component with well know example of calculating remaining character count.

Step 1: download Jquery javascript file

download the jquery latest version from the https://jquery.com/download/ .

Step 2: Upload to the static resource

Step 3: Time to code!

Here is the simple code that will display the total remaining character from the input text area.

<aura:component >
    <ltng:require scripts="{!$Resource.jQueryv3}"
                  afterScriptsLoaded="{!c.loadJquery}" />
    
    <aura:attribute name="text" type="String" default="" />
    
    <textarea id="textareaChars" maxlength="100" value="{!v.text}"></textarea> <br/>
    
    <span id="chars">100</span> characters remaining   
    
</aura:component>

 

({
    loadJquery : function(component, event, helper) {
        jQuery(document).ready(function(){
            var maxLength = 100;
            $('textarea').keyup(function() {
                var length = $(this).val().length;
                var length = maxLength-length;
                $('#chars').text(length);
            });
        });
    }
})

 

1. Load the Jquery from Static Resource by using ltng:require  . Load the Jquery functionality on afterScriptsLoaded method.

<ltng:require scripts="{!$Resource.jQueryv3}" afterScriptsLoaded="{!c.loadJquery}" />

2.  Load Jquery document  Read method inside the loadJquery function

jQuery(document).ready(function(){
}

3. Use the keyup event on the textarea, which fires each time a key is pressed when the textarea is in focus. Ideal:

$('textarea').keyup(function() {

4. Check the value and get the length of it, store it in a variable:

var length = $(this).val().length;

5. Take that value away from your max width:

var length = maxLength-length;

6. Put the result somewhere on the page:

$('#chars').text(length);

Using Promise In Lightning Component

Introduction 

In this blog, I am going to explain how to use Promise in the lightning component. Salesforce lightning components had improved performance by its asynchronous nature itself by managing the lifecycle. Promises are one of the ways to deal with asynchronous code in JavaScript without writing callbacks. A promise is commonly defined as a proxy for a value that will eventually become available. For example, if you use the promise API to make an asynchronous call to a web service, you will create a Promise object which represents the data that will be returned by the web service in future. The caveat is that the actual data isn’t available yet. It will become available when the request completes and a response comes back from the web service. In the meantime, the Promise object acts as a proxy to the actual data. Furthermore, you can attach callbacks to the Promise object, which will be called once the actual data is available.

How Promises Work

The promise is asynchronous so when Promise is executed it contains different status. When a promise is pending, it can transition to the fulfilled or rejected state. Once a promise is fulfilled or rejected, however, it will never transition to any other state, and its value or failure reason will not change. A promise can be in one of 3 states:

  • Pending – the promise’s outcome hasn’t yet been determined
  • Fulfilled – the asynchronous operation has completed
  • Rejected – the asynchronous operation failed.

Create a Promise

The Promise object is created using the new keyword and its constructor. This constructor takes as its argument a function, called the “executor function”. This function should take two functions as parameters. The first of these functions (resolve) is called when the asynchronous task completes successfully and returns the results of the task as a value. The second (reject) is called when the task fails and returns the reason for failure, which is typically an error object The promise syntax looks like as shown below.

new Promise(/* executor*/ function (resolve, reject) { ... } );

To provide a function with promise, simply have it return a promise. The following serverSideCall function is returning the Promise object. Once the promise object returns the success response, it will invoke the resolve otherwise it will invoke reject.

({
    serverSideCall : function(component,action) {
        return new Promise(function(resolve, reject) { 
            action.setCallback(this, 
                               function(response) {
                                   var state = response.getState();
                                   if (state === "SUCCESS") {
                                       resolve(response.getReturnValue());
                                   } else {
                                       reject(new Error(response.getError()));
                                   }
                               }); 
            $A.enqueueAction(action);
        });
    },
  
    
})

Now all the functions get the promise object instance.

const promise = serverSideCall (); 

after creating the promise object instance you need to call the then() method. All promise instances get a then method which allows you to react to the promise.

promise.then(successCallback, failureCallback);
 Or simply
serverSideCall().then(successCallback, failureCallback);

Chaining Promises

When you need to coordinate or chain together multiple callbacks, promises can be useful. The generic pattern is:

var exeAction = component.get("c.executeMethod1");
 exeAction.setParams( {"message": 'Promise are cool way to handle callback'});
 helper.serverSideCall(component,exeAction).then(
 function(res) {
 var exeAction2 = component.get("c.executeMethod2");
 exeAction2.setParams( {"message": 'Promise are cool way to handle callback'});
 return helper.serverSideCall(component,exeAction2) ;
 
 }
 ).then(
 function(res) {
 var exeAction3 = component.get("c.executeMethod3");
 exeAction3.setParams( {"message": 'Promise are cool way to handle callback'});
 return helper.serverSideCall(component,exeAction3) ;
 }
 )
 .catch(
 function(error) {
 component.set("v.status" ,error ) ; 
 console.log(error);
 }
 );

Orchestrating promises

If you need to synchronize different promises, Promise.all() helps you define a list of promises, and execute something when they are all resolved.

 var exeAction1 = component.get("c.executeMethod1");
        var exeAction2 = component.get("c.executeMethod2");
        var exeAction3 = component.get("c.executeMethod3");
        var exeAction4 = component.get("c.executeMethod4");
        var exeAction5 = component.get("c.executeMethod5");
        exeAction1.setParams( {"message": 'Promise are cool way to handle callback executeMethod1'});
        exeAction2.setParams( {"message": 'Promise are cool way to handle callback executeMethod2'});
        exeAction3.setParams( {"message": 'Promise are cool way to handle callback executeMethod3'});
        exeAction4.setParams( {"message": 'Promise are cool way to handle callback executeMethod4'});
        exeAction5.setParams( {"message": 'Promise are cool way to handle callback executeMethod5'});
        Promise.all([
            helper.serverSideCall(component,exeAction1),
            helper.serverSideCall(component,exeAction2) ,
            helper.serverSideCall(component,exeAction3) ,
            helper.serverSideCall(component,exeAction4) ,
            helper.serverSideCall(component,exeAction5) 
            
        ]).then(
            function(response) {
                console.log(response);
                component.set("v.status" ,"Success" ) ; 
                
                component.set("v.statusArray" ,response[0] ) ; 
                
            }
        ).catch(
            function(error) {
                component.set("v.status" ,error ) ; 
                console.log(error);
            }
        );

Promise.race()

Use of Promise.race Instead of waiting for all promises to be resolved or rejected, Promise.race triggers as soon as any promise in the array is resolved or rejected

var exeAction1 = component.get("c.executeMethod1");
        var exeAction2 = component.get("c.executeMethod2");
        
        exeAction1.setParams( {"message": 'Promise are cool way to handle callback executeMethod1'});
        exeAction2.setParams( {"message": 'Promise are cool way to handle callback executeMethod2'});
        let var1 =    helper.serverSideCall(component,exeAction1);
        let var2 =helper.serverSideCall(component,exeAction2);
        
        Promise.race([var1, var1]).then(
            function(res) {
                var exeAction3 = component.get("c.executeMethod3");
                exeAction3.setParams( {"message": 'Promise are cool way to handle callback'});
                return helper.serverSideCall(component,exeAction3) ;
            }
        )
        .catch(
            function(error) {
                component.set("v.status" ,error ) ; 
                console.log(error);
            }
        );

 

Handling Errors

What if an error occurs while performing an asynchronous operation?  In synchronous code, you can use try/catch, and rely on exception propagation to errors handle. The Promises API includes a catch() method to optionally catch unhandled errors. Always include a reject handler or a catch() method in your promise chain. Throwing an error in a promise doesn’t trigger window.onerror, which is where the framework configures its global error handler. If you don’t have a catch() method, keep an eye on your browser’s console during development for reports about uncaught errors in a promise. To show an error message in a catch() method, use $A.reportError().

 var exeAction = component.get("c.executeMethod1");
        helper.serverSideCall(component,exeAction).then(
            function(res) {
            }
        ).catch(
            function(error) {
                component.set("v.status" ,error ) ; 
                console.log(error);
            }
        );

 

Time to code 

Here is the complete code that will demonstrate different ways of promise usage

Apex Class

 

public class PromiseController {
    @AuraEnabled
    public static String executeMethod1(String message ){
        return ' From Server executeMethod1 -->' +message ;
    }
    @AuraEnabled
    public static String executeMethod2(String message ){
        return ' From Server executeMethod2 -->' +message ;
    }
    @AuraEnabled
    public static String executeMethod3(String message ){
        return ' From Server  executeMethod3-->' +message ;
    } @AuraEnabled
    public static String executeMethod4(String message ){
        return ' From Server executeMethod4 -->' +message ;
    } @AuraEnabled
    public static String executeMethod5(String message ){
        return ' From Server executeMethod5-->' +message ;
    }
}

 

Lightning Component

<aura:component controller="PromiseController">
    
    <aura:attribute name="status" type="String"  default="Not started" />
    <aura:attribute name="statusArray" type="String[]"  />
    
    <ui:button label="Simple Promise Based Execution " press="{!c.promiseExecution}" />
    <ui:button label="PromiseChaining " press="{!c.promiseChaining}" />
    <ui:button label="Orchestrating promises " press="{!c.promiseOrchestration}" />
    <ui:button label="Promise.race() " press="{!c.promiseRace}" />
    <ui:button label="Error Handling  " press="{!c.promiseError}" />
    <div>
        {!v.status}
    </div>
    Orchestrating promises Response -
    <div>
        {!v.statusArray}
    </div>
    
</aura:component>

controller

({
    promiseExecution : function(component, event, helper) {
        var exeAction = component.get("c.executeMethod1");
        exeAction.setParams( {"message": 'Promise are cool way to handle callback'});
        helper.serverSideCall(component,exeAction).then(
            function(res) {
                component.set("v.status" ,res ) ; 
            }
        ).catch(
            function(error) {
                component.set("v.status" ,error ) ; 
                console.log(error);
            }
        );
    },
    promiseOrchestration : function(component, event, helper) {
        var exeAction1 = component.get("c.executeMethod1");
        var exeAction2 = component.get("c.executeMethod2");
        var exeAction3 = component.get("c.executeMethod3");
        var exeAction4 = component.get("c.executeMethod4");
        var exeAction5 = component.get("c.executeMethod5");
        exeAction1.setParams( {"message": 'Promise are cool way to handle callback executeMethod1'});
        exeAction2.setParams( {"message": 'Promise are cool way to handle callback executeMethod2'});
        exeAction3.setParams( {"message": 'Promise are cool way to handle callback executeMethod3'});
        exeAction4.setParams( {"message": 'Promise are cool way to handle callback executeMethod4'});
        exeAction5.setParams( {"message": 'Promise are cool way to handle callback executeMethod5'});
        Promise.all([
            helper.serverSideCall(component,exeAction1),
            helper.serverSideCall(component,exeAction2) ,
            helper.serverSideCall(component,exeAction3) ,
            helper.serverSideCall(component,exeAction4) ,
            helper.serverSideCall(component,exeAction5) 
            
        ]).then(
            function(response) {
                console.log(response);
                component.set("v.status" ,"Success" ) ; 
                
                component.set("v.statusArray" ,response[0] ) ; 
                
            }
        ).catch(
            function(error) {
                component.set("v.status" ,error ) ; 
                console.log(error);
            }
        );
    },
    promiseChaining : function(component, event, helper) {
        var exeAction = component.get("c.executeMethod1");
        exeAction.setParams( {"message": 'Promise are cool way to handle callback'});
        helper.serverSideCall(component,exeAction).then(
            function(res) {
                var exeAction2 = component.get("c.executeMethod2");
                exeAction2.setParams( {"message": 'Promise are cool way to handle callback'});
                return helper.serverSideCall(component,exeAction2) ;
                
            }
        ).then(
            function(res) {
                var exeAction3 = component.get("c.executeMethod3");
                exeAction3.setParams( {"message": 'Promise are cool way to handle callback'});
                return helper.serverSideCall(component,exeAction3) ;
            }
        )
        .catch(
            function(error) {
                component.set("v.status" ,error ) ; 
                console.log(error);
            }
        );
    },
    promiseRace : function(component, event, helper) {
        var exeAction1 = component.get("c.executeMethod1");
        var exeAction2 = component.get("c.executeMethod2");
        
        exeAction1.setParams( {"message": 'Promise are cool way to handle callback executeMethod1'});
        exeAction2.setParams( {"message": 'Promise are cool way to handle callback executeMethod2'});
        let var1 =    helper.serverSideCall(component,exeAction1);
        let var2 =helper.serverSideCall(component,exeAction2);
        
        Promise.race([var1, var1]).then(
            function(res) {
                var exeAction3 = component.get("c.executeMethod3");
                exeAction3.setParams( {"message": 'Promise are cool way to handle callback'});
                return helper.serverSideCall(component,exeAction3) ;
            }
        )
        .catch(
            function(error) {
                component.set("v.status" ,error ) ; 
                console.log(error);
            }
        );
        
        
        
    },
    promiseError : function(component, event, helper) {
        var exeAction = component.get("c.executeMethod1");
        helper.serverSideCall(component,exeAction).then(
            function(res) {
            }
        ).catch(
            function(error) {
                component.set("v.status" ,error ) ; 
                console.log(error);
            }
        );
    }
    
})

 

helper

({
    serverSideCall : function(component,action) {
        return new Promise(function(resolve, reject) { 
            action.setCallback(this, 
                               function(response) {
                                   var state = response.getState();
                                   if (state === "SUCCESS") {
                                       resolve(response.getReturnValue());
                                   } else {
                                       reject(new Error(response.getError()));
                                   }
                               }); 
            $A.enqueueAction(action);
        });
    },
  
    
})

 

 

 

lightning:progressIndicator

A lightning:progressIndicator component displays a horizontal list of steps in a process, indicating the number of steps in a given process, the current step, as well as prior steps completed. For example, Sales Path uses a progress indicator to guide sales reps through the stages of the sales process. You can create progress indicators with different visual styling by specifying the type attribute. Set type=”base” to create a component that inherits styling from progress indicators in the Lightning Design System. Set type=”path” to create a component that inherits styling from the path in the Lightning Design System.

In this exmaple, I am showing the step wizard sort of form along with the progress  indicators as shown below

 

<aura:component implements="force:appHostable" >
    <aura:attribute name="accountId" type="String" />
    <aura:attribute name="contactId" type="String" />
    <aura:attribute name="opportunityId" type="String" />
    <aura:attribute name="caseId" type="String" />
    <aura:attribute name="currentStepInd" type="Integer" default="1"/>
    <aura:attribute name="isProgressing" type="Boolean" default="false"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    <lightning:progressIndicator currentStep="{!v.currentStepInd}" type="base" hasError="false" variant="base">
        <lightning:progressStep label="Account" value="1"/>
        <lightning:progressStep label="Contact" value="2"/>
        <lightning:progressStep label="Opportunity" value="3"/>
        <lightning:progressStep label="Case" value="4"/>
        <lightning:progressStep label="Result" value="5"/>
        
    </lightning:progressIndicator>
    <div  aura:id="accountRec">
        <lightning:card iconName="standard:account" title="Lightning ProgressBar - Account Information" variant="base" class="slds-card-wrapper">
            <lightning:recordEditForm
                                      onsubmit="{!c.handlerSubmit}"
                                      recordTypeId ="012i0000000ALExAAO"
                                      objectApiName="Account">
                <!-- the messages component is for error messages -->
                <lightning:messages />
                
                <lightning:inputField fieldName="Name" />
                <lightning:inputField fieldName="Type" />
                <lightning:inputField fieldName="Phone" />
                <lightning:inputField fieldName="Rating" />
                <div class="slds-m-top_medium">
                    <lightning:button  variant="brand" type="submit" name="save" label="Save Account" onclick="{!c.handlerSubmit}" />
                </div>
            </lightning:recordEditForm>
            
        </lightning:card>
    </div>
    <div aura:id="conRec">
        <lightning:card iconName="standard:contact" title="Lightning ProgressBar - Contact Information" variant="base" class="slds-card-wrapper">
            <lightning:recordEditForm
                                      onsubmit="{!c.handlerSubmit}"
                                      recordTypeId ="012i00000019hcLAAQ"
                                      objectApiName="Contact">
                <!-- the messages component is for error messages -->
                <lightning:messages />
                <lightning:inputField fieldName="FirstName" />
                <lightning:inputField fieldName="LastName" />
                <lightning:inputField fieldName="Email" />
                <lightning:inputField fieldName="Phone" />
                <div class="slds-m-top_medium">
                    <lightning:button  variant="brand" type="submit" name="save" label="Save Contact" onclick="{!c.handlerSubmit}"/>
                </div>
            </lightning:recordEditForm>
        </lightning:card>
    </div>
    <div aura:id="oppRed">
        <lightning:card iconName="standard:opportunity" title="Lightning ProgressBar - Opportunity Information" variant="base" class="slds-card-wrapper">
            <lightning:recordEditForm
                                      onsubmit="{!c.handlerSubmit}"
                                      objectApiName="Opportunity">
                <!-- the messages component is for error messages -->
                <lightning:messages />
                <lightning:inputField fieldName="Name" />
                <lightning:inputField fieldName="Amount" />
                <lightning:inputField fieldName="CloseDate" />
                <lightning:inputField fieldName="StageName" />
                <lightning:inputField fieldName="Type" />
                <div class="slds-m-top_medium">
                    <lightning:button  variant="brand" type="submit" name="save" label="Save Opportunity" onclick="{!c.handlerSubmit}"/>
                </div>
            </lightning:recordEditForm>
        </lightning:card> 
    </div>
    <div aura:id="caseRec">
        <lightning:card iconName="standard:case" title="Lightning ProgressBar - Case Information" variant="base" class="slds-card-wrapper">
            <lightning:recordEditForm
                                      onsubmit="{!c.handlerSubmit}"
                                      recordTypeId ="012i0000001AOvJAAW"
                                      objectApiName="Case">
                <!-- the messages component is for error messages -->
                <lightning:messages />
                <lightning:inputField fieldName="Account" />
                <lightning:inputField fieldName="Subject" />
                <lightning:inputField fieldName="Origin" />
                <lightning:inputField fieldName="Reason" />
                <lightning:inputField fieldName="Contact" />
                <lightning:inputField fieldName="Priority" />
                <lightning:inputField fieldName="Type" />
                <div class="slds-m-top_medium">
                    <lightning:button  variant="brand" type="submit" name="save" label="Save Case" onclick="{!c.handlerSubmit}" />
                </div>
            </lightning:recordEditForm>
            
        </lightning:card>
    </div>
    
    <div aura:id="result">
        <lightning:card iconName="standard:case" title="Lightning ProgressBar - Completed Information" variant="base" class="slds-card-wrapper">
            Save is Successfull 
        </lightning:card>
    </div>
    
    
</aura:component>

 

({
    
    doInit : function(component, event, helper) {
        component.set("v.currentStepInd" ,1);
        
        var toggleText = component.find("conRec");
        $A.util.addClass(toggleText,'toggle');
        toggleText = component.find("oppRed");
        $A.util.addClass(toggleText,'toggle');         
        toggleText = component.find("caseRec");
        $A.util.addClass(toggleText,'toggle'); 
        
        toggleText = component.find("result");
        $A.util.addClass(toggleText,'toggle'); 
        
    },
    
    handlerSubmit: function (component,event) {
        
        var strLabel = event.getSource().get("v.label");
        console.log(strLabel);
        if(strLabel=='Save Account'){
            component.set("v.currentStepInd" ,"2");
            var toggleText = component.find("conRec");
            $A.util.removeClass(toggleText,'toggle');
            var toggleText = component.find("accountRec");
            $A.util.addClass(toggleText,'toggle');
            toggleText = component.find("oppRed");
            $A.util.addClass(toggleText,'toggle');         
            toggleText = component.find("caseRec");
            $A.util.addClass(toggleText,'toggle'); 
        }
        if(strLabel=='Save Contact'){
            component.set("v.currentStepInd" ,"3");
            var toggleText = component.find("oppRed");
            $A.util.removeClass(toggleText,'toggle');
            var toggleText = component.find("accountRec");
            $A.util.addClass(toggleText,'toggle');
            toggleText = component.find("conRec");
            $A.util.addClass(toggleText,'toggle');         
            toggleText = component.find("caseRec");
            $A.util.addClass(toggleText,'toggle'); 
        }
        if(strLabel=='Save Opportunity'){
            component.set("v.currentStepInd" ,"4");
            var toggleText = component.find("caseRec");
            $A.util.removeClass(toggleText,'toggle');
            var toggleText = component.find("accountRec");
            $A.util.addClass(toggleText,'toggle');
            toggleText = component.find("oppRed");
            $A.util.addClass(toggleText,'toggle');         
            toggleText = component.find("conRec");
            $A.util.addClass(toggleText,'toggle'); 
        }
        if(strLabel=='Save Case'){
            component.set("v.currentStepInd" ,"5");
            var toggleText = component.find("conRec");
            $A.util.addClass(toggleText,'toggle');
            var toggleText = component.find("accountRec");
            $A.util.addClass(toggleText,'toggle');
            toggleText = component.find("oppRed");
            $A.util.addClass(toggleText,'toggle');         
            toggleText = component.find("caseRec");
            $A.util.addClass(toggleText,'toggle'); 
            var toggleText = component.find("result");
            $A.util.removeClass(toggleText,'toggle');
            
        }
      
        
    }
})

 

.THIS.toggle {
    display: none;
}
.THIS {
    background-color: #fff;
}