Lightning · Salesforce · Salesforce Releases

Usage of Spring ’19 component — lightning:unsavedChanges

Accidents are commonplace! And yeah, Spring  ’19 has come up with a new component lightning:unsavedChanges. Voila!!

We often come across situations where we type in data and then we accidentally refreshes, closes the page or press back button and all the entered data is lost!!  lightning:unsavedChanges  comes in to help here! It notifies the user about the unsaved changes in the page during the above mentioned situations and provides them the choice to continue, discard or save the data and handles the process accordingly. No more frustrations over data loss!!

Before we move ahead, it would be handy to remember that this component requires API version 45.0 or later and is not supported by one.app

In this blog, we demonstrate a sample of how this component works.

	 <aura:component controller="unsavedChangesClass" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" >
		<lightning:unsavedChanges aura:id="unsavedData"
								  onsave="{!c.handleSave}"
								  ondiscard="{!c.handleDiscard}"/>
		<aura:attribute name="contactDetail" type="Contact" default="{'sobjectType' : 'Contact'}"/>

		<lightning:card title="Create Related Contact">
			<lightning:input aura:id="firstName"  label="FirstName"  value="{!v.contactDetail.firstName}" onchange="{!c.handleDataChange}"/><br/>
			<lightning:input aura:id="lastName"  label="LastName"  required="true" value="{!v.contactDetail.LastName}" onchange="{!c.handleDataChange}"/><br/>
			<lightning:input aura:id="phone"  label="Phone"   value="{!v.contactDetail.Phone}" onchange="{!c.handleDataChange}"/><br/>
			<lightning:button variant="brand"  label="Create Contact" onclick="{!c.saveContact}"/>
		</lightning:card>
	</aura:component>
	

CONTROLLER


    ({
    //Method call on Create Button Click
    saveContact : function(component, event, helper){
        helper.createContact(component, event);
    },

    /*This method sets the boolean for unsavedChanges to true,
     * so that it indicates the containment that unsaved data is rpesent
     * */
    handleDataChange: function(component, event, helper) {
        var unsavedData = component.find('unsavedData');
        unsavedData.setUnsavedChanges(true, {label: 'creating related contact?'});
    },

    /**
     * This method will be called when user click save button from dialog window
     * Save your unsaved changes here
     * */
    handleSave: function(component, event, helper) {
        helper.createContact(component, event);
    },

    /**
     * This method will be called when user clicks 'discard changes' button from dialog window
     * */
    handleDiscard: function(component, event, helper) {
        var unsavedData = component.find('unsavedData');
        unsavedData.setUnsavedChanges(false);
      }
})

HELPER

({
    createContact : function(component, event){
        var action = component.get('c.createContact');
        action.setParams({'accId' : component.get('v.recordId'),
                          'lName' : component.find('lastName').get('v.value')});
        action.setCallback(this, function(response){
            var state = response.getState();
            if(state === 'SUCCESS'){
                var unsavedData = component.find('unsavedData');
                unsavedData.setUnsavedChanges(false);

                var navEvt = $A.get("e.force:navigateToSObject");	//To navigate
                navEvt.setParams({
                    "recordId": response.getReturnValue().Id,
                });
                navEvt.fire();
            }else{
                console.log('error');
            }
        });
        $A.enqueueAction(action);
    }
})

APEX

public with sharing class unsavedChangesClass {
    @AuraEnabled
    public static Contact createContact(Id accId, String lName){
        Contact con = new Contact(lastname=lName,
                                 accountId = accId);
        insert con;
        return con;
    }
}

The process is majorly handled by the function setUnsavedChanges within the lightning component.  This method holds two arguments  –

  • A Boolean argument to indicate if usaved data is present in the page or not. (True if unsaved content is present, false otherwise)
  • An optional object argument.

Upon data entry, we set the setUnsavedChanges to true; And therefore, when the user takes any action that loses data, it notifies the containment that unsaved data is present in the page and the dialogue window pops up as shown in the screenshot. Now, depending on the user’s decision, the handleSave  or handleDiscard custom methods will be invoked. The onsave attribute controls the action to  handle saving unsaved content  and the  ondiscard attribute  controls the action to handle discarding unsaved content. Also, keep in mind that, these methods should call the setUnsavedChanges() method again to return control back to the Lightning UI.

 

3 thoughts on “Usage of Spring ’19 component — lightning:unsavedChanges

  1. Hey 🙂 I’m having an issue, exactly the other way around.
    I am working on an app where I need to skip the standard UnsavedChanges prompt. When a user clicks save on a record I catch this by addError() method, I then want to make the user interact with a modal I show and when they click save on my modal, I want it to simply close the edit view or reload the page to show the record page without edit mode. Do you know if there is a way to do so?

    thanks and best regards,
    Alex

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s