Sunday, December 17, 2017

Crate a lightning component to update record.

Scenario: Suppose we have a Student object with 2 custom field Roll No and Class and assume that we have a student record, which we want to update. Now our aim is to create a lightning component to update Student record and to access this component we will override standard edit button of student object.

Solution: To solve the above scenario please follow the below steps,

1. Create a Student Object with below fields,
  • Standard field "Student Name" will automatically created.
  • Create 2 custom fields,
  1. Roll No        Roll_No__c     Number(18, 0)
  2. Class            Class__c          Text(10)


2. Create a lightning component named as "UpdateStudent" (To create lightning component please check my previous post, where I mentioned details with screen shots).

In the component header implements="lightning:actionOverride" . This is because we want to override standard edit button of this component (UpdateStudent).
And also implements="force:hasRecordId". This is because we need to display existing record on the time of component load by it's record id.

Now the component is look like this,



3. Now create a server side controller class and named it as "UpdateStudentCtrl", where we create logic for update student record.
Now this controller should have 2 methods and each should be annotated with <@AuraEnabled>,

  • updateStudent(Student__c student) ==> to update student record.
  • fetchStudentDetails(Id studentId)    ==> to fetch student details. This is required because, we need to show the details of student (name, roll no, class) on the time of component load.

/**
  * @name:        UpdateStudentCtrl      
  * @date:        15 Dec 2017
  * @description: This is the server side controller class for <UpdateStudent> lightning component.
  *             Server side update, fetch record will be perform here.
***/
public with sharing class UpdateStudentCtrl{
    /**
  * @name:        saveStudent      
  * @date:        17 Dec 2017
  * @description: This method is responsible to update student record. As this method is calling from
  *            client side lighthing component, so this should be annoted with <@AuraEnabled>.
  ***/
    @AuraEnabled
    public static void updateStudent(Student__c student){
        UPDATE student;
    }
    
    /**
  * @name:        fetchStudentDetails      
  * @date:        17 Dec 2017
  * @description: This method is responsible to fetch student record based on student id. As this method is calling from
  *            client side lighthing component, so this should be annoted with <@AuraEnabled>.
  ***/
    @AuraEnabled
    public static Student__c fetchStudentDetails(Id studentId) {
        List<Student__c> lstOfStd = new List<Student__c>();
        if(studentId != null)    
         lstOfStd = [SELECT Id, Name, Roll_No__c, Class__c FROM Student__c WHERE Id = :studentId];
        if(! lstOfStd.isEmpty())
         return lstOfStd.get(0);
        
        return null;
    }
}

3. Now in our component we have to create 3 input fields (Student Name, Roll No and Class) and two buttons (Save, Cancel). On the initial load of component the fields should have their existing values.
Click on Cancel button will hide or close the "Edit Student" window and click on Save will update the student record.

Now just copy paste the below component and it's client side controller. Details descriptions have been describe in code base.


=======================================================
=======================================================
<!-- UpdateStudent.cmp -->
<aura:component implements="lightning:actionOverride,force:hasRecordId"
                             controller="UpdateStudentCtrl">
    
    <!-- Attribute declaration -->
    <aura:attribute name="studentObj" type="Student__c" default="{ 'sobjectType': 'Student__c'}"/>
    
    <!-- hadlerMethod declaration -->
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <!--/ hadlerMethod declaration -->
    
    <!-- modal -->
    <div aura:id="modalIdForEditStudent" role="dialog" tabindex="-1" aria-labelledby="header41" class="slds-modal slds-fade-in-open">
        <div class="slds-modal__container">
            <!-- header -->
            <div class="slds-modal__header">
                <h2 id="header43" class="slds-text-heading--medium">
                    Edit Student
                </h2>
            </div>
            <!--/ header -->
            <!-- modal body -->
            <div class="slds-form slds-grid slds-wrap slds-modal__content">                
                <div class="slds-col--padded slds-size--1-of-1">
                    <div class="slds-form-element">
                        <lightning:input aura:id="stdName"
                                         label="Student Name"
                                         type="String"
                                         required="true"
                                         value="{!v.studentObj.Name}"/>
                    </div>
                </div>
                <div class="slds-col--padded slds-size--1-of-1">
                    <div class="slds-form-element">
                        <lightning:input aura:id="stdClass"
                                         label="Class"
                                         type="String"
                                         value="{!v.studentObj.Class__c}"/>
                    </div>
                </div>
                <div class="slds-col--padded slds-size--1-of-1">
                    <div class="slds-form-element">
                        <lightning:input aura:id="stdRoll"
                                         label="Roll No"
                                         type="Number"
                                         value="{!v.studentObj.Roll_No__c}"/>
                    </div>
                </div>
            </div>
            <!--/ modal body -->
            
            <!-- modal footer -->
            <div class="slds-modal__footer">
                <!-- Button -->
                <lightning:button aura:id="cancelId"
                                  label="Cancel"
                                  variant="brand"
                                  onclick="{!c.doCancel}"/>
                <lightning:button aura:id="saveId"
                                  label="Save"
                                  variant="neutral"
                                  onclick="{!c.doSave}"/>    
            </div>
        </div>        
    </div>
    <!--/ modal footer -->
    
    <div aura:id="backdropIdForEditStudent" class="slds-backdrop slds-backdrop--open"/>   
</aura:component>
===========================================================
===========================================================
//UpdateStudentController.js
({
    /**
     * @name:    doInit      
     * @date:        17 DEC 2017
     * @description: This method is handler method of UpdateStudent component and hence it will be
     *      call on the time of component initial load.
     *      This method is responsible to fetch the existing record.
     **/
    doInit : function(component, event, helper) {
        //Calling server side controller's fetchStudentDetails() method.
        var action = component.get("c.fetchStudentDetails");
        //Set method parameter of updateStudent() method, where "v.recordId" returns object record id of current screen.
        action.setParams({"studentId": component.get("v.recordId")});
        
        action.setCallback(this, function(response){
            //<response.getState()> return response status as SUCCESS/ERROR/INCOMPLETE etc.
            var state = response.getState();
            console.log("state="+state)
            //If response from server side is <SUCCESS>, then we will set the component attribute "studentObj".
            if (state === "SUCCESS"){
                var responseStudentRecord = response.getReturnValue();
                component.set("v.studentObj", responseStudentRecord);
            }else if (state === "INCOMPLETE") {
                //Offline message display logic.
                var toastEvent = $A.get("e.force:showToast");
                toastEvent.setParams({
                    "title": "OFFLINE!",
                    "message": "You are in offline."
                });
                toastEvent.fire();
            }else if (state === "ERROR") {
                //Error message display logic.
                var errors = response.getError();
                var toastEvent = $A.get("e.force:showToast");
                toastEvent.setParams({
                    "title": "ERROR!",
                    "message": errors[0].message
                });
                toastEvent.fire();
            }else {
                //Unknown message display logic.
                var toastEvent = $A.get("e.force:showToast");
                toastEvent.setParams({
                    "title": "UNKOWN!",
                    "message": "Unknown error."
                });
                toastEvent.fire();
            }
        });
        
        $A.enqueueAction(action);
    },
    
    /**
     * @name:    doCancel      
     * @date:        17 DEC 2017
     * @description: This method is responsible to cancel or close the modal window.
     **/
    doCancel : function(component, event, helper) {
        var cmpTargetForEdit = component.find('modalIdForEditStudent');
        var cmpBackDropForEdit = component.find('backdropIdForEditStudent');
        $A.util.removeClass(cmpBackDropForEdit,'slds-backdrop--open');
        $A.util.removeClass(cmpTargetForEdit, 'slds-fade-in-open');
    },
    
    /**
     * @name:    doSave      
     * @date:        17 DEC 2017
     * @description: This method is responsible to save student record.
     **/
    doSave : function(component, event, helper) {
  /** Server side controller calling logic. **/
        
        //Calling server side controller's updateStudent() method.
        var action = component.get("c.updateStudent");
        //Set method parameter of updateStudent() method.
        action.setParams({"student": component.get("v.studentObj")});
        
        action.setCallback(this, function(response){
            //<response.getState()> return response status as SUCCESS/ERROR/INCOMPLETE etc.
            var state = response.getState();
            console.log("state="+state)
            //If response from server side is <SUCCESS>, then we will display a success message.
            if (state === "SUCCESS"){
                //Success message display logic.
                var toastEvent = $A.get("e.force:showToast");
                toastEvent.setParams({
                    "title": "Success!",
                    "message": "Student record has been updated successfully."
                });
                toastEvent.fire();
                
                //Navigate to detail page.
                window.location ="/"+component.get("v.recordId");
            }else if (state === "INCOMPLETE") {
                //Offline message display logic.
                var toastEvent = $A.get("e.force:showToast");
                toastEvent.setParams({
                    "title": "OFFLINE!",
                    "message": "You are in offline."
                });
                toastEvent.fire();
            }else if (state === "ERROR") {
                //Error message display logic.
                var errors = response.getError();
                var toastEvent = $A.get("e.force:showToast");
                toastEvent.setParams({
                    "title": "ERROR!",
                    "message": errors[0].message
                });
                toastEvent.fire();
            }else {
                //Unknown message display logic.
                var toastEvent = $A.get("e.force:showToast");
                toastEvent.setParams({
                    "title": "UNKOWN!",
                    "message": "Unknown error."
                });
                toastEvent.fire();
            }
        });
        
        $A.enqueueAction(action);
 }
})

4. Now we have to override standard edit button of Student record with the above created lightning component. For the same go to "Buttons, Links, and Actions" link of Student object and then edit the edit button and override our lightning component (UpdateStudent).




















Edit button override step:

















5. Once the above step done, then open any student record and click on edit button will open our component as a modal window with existing record value.
For testing, change the input field and click on save button will save the record with success message and finally redirect to student detail page with updated value.

=> Existing student record.











=> Click on Edit button will open modal window with existing value.












=> Modal window with updated value.













=> Click on save button will save the record with success message















=> Finally it will redirect to student detail page with updated value.

LWC to LWC Communication using Lightning Messaging Service (Part - 2)

In my previous post ( previous post link ) we have learn how to create a Lightning Messaging Service with 6 steps and today we will use the ...