Today I am going to walk through a new feature introduced by Salesforce - Lightning Data Services.
This is not yet generally available. It is available as developer preview.
Lightning data services allows you to view, create, update and delete a record without using server-side Apex controllers. You can compare this with Standard Controller on VF page which allows you to read, create, update or delete records by providing in built functions like Save, Edit,Delete etc.
Other benefit of using Lightning data services is that all records are cached and shared across all components. This improves the performance because record is loaded only once.
If any component modifies the record, then other component using this records get notified and refresh automatically.
In order to use Lightning data services, you need to use force:recordPreview tag and need to specify recordId while performing any operation.
Now we will cover how to use Lightning data services for different operations.
Before Summer'17 below was syntax which is now depricated.
<force:recordPreview aura:id="recordLoader"
RAISING AND HANDLING CUSTOM EVENTS IN sALESFORCE lIGHTNING
WHY TO USE DESIGN RESOURCE AND HOW TO ADD DYNAMIC OPTION TO DATASOURCE
PASSING INNER WRAPPER CLASS TO LIGHTNING COMPONENT
LIGHTNING COMPONENT FOR RECORDTYPE SELECTION FOR ANY SOBJECT
This is not yet generally available. It is available as developer preview.
What is lightning data services?
Lightning data services allows you to view, create, update and delete a record without using server-side Apex controllers. You can compare this with Standard Controller on VF page which allows you to read, create, update or delete records by providing in built functions like Save, Edit,Delete etc.
Other benefit of using Lightning data services is that all records are cached and shared across all components. This improves the performance because record is loaded only once.
If any component modifies the record, then other component using this records get notified and refresh automatically.
In order to use Lightning data services, you need to use force:recordPreview tag and need to specify recordId while performing any operation.
Now we will cover how to use Lightning data services for different operations.
- Load Record (View Record)
In order to Load record information on lightning component, you need to pass recordId. It is similar to pass id parameter in URL in VF page while using standard controller.
<force:recordData aura:id="recordLoader"
recordId="xxxxxxxxxxxxx"
layoutType="FULL"
targetRecord="{!v.record}"
targetFields="{!v.recordInfo}"
targetFields="{!v.recordInfo}"
targetError="{!v.recordError}"
/>
Before Summer'17 below was syntax which is now depricated.
<force:recordPreview aura:id="recordLoader"
recordId="xxxxxxxxxxxxx"
layoutType="FULL"
targetRecord="{!v.record}"
targetError="{!v.recordError}"
/>
recordId: It is 15 or 18 digit recordId.
targetRecord: This contains complete info about record.
targetFields : A simplified view of the fields in targetRecord, to reference record fields in component markup.
targetFields : A simplified view of the fields in targetRecord, to reference record fields in component markup.
targetError : This specify any error if lightning data services is not successfull in geting record details based on recordId provided.
- Edit Record
For editing records, you need use same force:recordPreview tag and you can use additional attribute mode to specify you are editing record.
<force:recordData aura:id="recordHandler"
recordId="xxxxxxxxxxxx"
layoutType="FULL"
targetRecord="{!v.record}"
targetFields="{!v.recordInfo}"
targetFields="{!v.recordInfo}"
targetError="{!v.recordError}"
mode="EDIT"
/>
Once you get access to record returned by Lightning Data Services in target record, then you can refer it in component to edit its field values. In order to Save the changes performed on record returned by Lightning data services, you can call javascript function to update records in database. In javascript function, you do not need to call apex class methods to update record but use functions provided by Lightning data services framework to perform this operation.
Below is javascript function code :
({
SaveRecord: function(component, event, helper) {
component.find("recordHandler").saveRecord($A.getCallback(function(saveResult) {
if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
//record got updated in salesforce
// Reload the view so that all components are refreshed after update
$A.get("e.force:refreshView").fire();
}
else {
var errMsg = 'Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error);
console.log(errMsg);
alert(errMsg);
}
}));
},
})
({
SaveRecord: function(component, event, helper) {
component.find("recordHandler").saveRecord($A.getCallback(function(saveResult) {
if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
//record got updated in salesforce
// Reload the view so that all components are refreshed after update
$A.get("e.force:refreshView").fire();
}
else {
var errMsg = 'Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error);
console.log(errMsg);
alert(errMsg);
}
}));
},
})
- Create Record
For creating a new record, you need to use same force:recordPreview tag but no need to specify the recordId attribute.
<force:recordData aura:id="accountRecordCreator"
layoutType="FULL"
targetRecord="{!v.newAccount}"
targetFields="{!v.newAccountInfo}"
targetFields="{!v.newAccountInfo}"
targetError="{!v.newAccountError}"
/>
In VF page, if you do not pass id parameter in URL and using standard controller, Save action creates new record in salesforce. Same way in Lightning data services, you do not need recordId for creating record.
You need to create a template of record so that it can be used to create new record. It is similar to initializing the sobject to avoid null pointer exception in apex controllers.
So in doInit function, first create template. Below is an example to create template for account:
doInit: function(component, event, helper) {
// Prepare a new record from template
component.find("accountRecordCreator").getNewRecord(
"Account", // sObject type (entity API name)
null, // record type (null if no recordtype exist
false, // skip cache?
$A.getCallback(function() {
var rec = component.get("v.newAccount"); //targetRecord attribute
var error = component.get("v.newAccountError");
if(error || (rec === null)) {
console.log("Error initializing record template: " + error);
}
else {
console.log("Record template initialized: " + rec.sobjectType);
}
})
);
},
In above code "newAccount" and "newAccountError" are component attribute which store information related to Lightning data services.
Now you have created a template and can use newAccount component attribute to specify field values on component. Once user specifies the field values, you can call javascript function on button click to create record. Below is sample code:
createContact: function(component, event, helper) {
component.find("accountRecordCreator").saveRecord(function(saveResult) {
if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
//record got created in salesforce
//show toast on UI with message
// Reload the view so that all components are refreshed after update
$A.get("e.force:refreshView").fire();
}
else {
var errMsg = 'Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error);
console.log(errMsg);
alert(errMsg);
}
});
},
If you want to modify any field value in javascript, then set the value in component attribute which hold object information. In our case attribute is "newAccount". So you can set value for "Type" field in Account (as shown below )then call saveRecord method.
- Delete Record
For delete also, you need to use force:recordPreview tag and need to specify the recordId and in fields specify Id.
<force:recordData aura:id="recordDeleteHandler"
recordId="{!v.recordId}"
fields="Id"
targetError="{!v.recordError}"
/>
In order to delete record on button click, call below mentioned controller function:
DeleteRecord: function(component, event, helper) {
component.find("recordDeleteHandler").deleteRecord($A.getCallback(function(saveResult) {
if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
//record got deleted from salesforce
// Reload the view so that all components are refreshed after update
$A.get("e.force:refreshView").fire();
}
else {
var errMsg = 'Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error);
console.log(errMsg);
alert(errMsg);
}
}));
}
I have created a component which will will display list of Account by using Apex controller and then I am creating, editing, viewing and deleting records using Lightning Data Services. For all DMl operation on this component, I am not using server-side apex controller and performing these operations using code snippet shown above.
I have created different components as mentioned below:
- AccountListView : This will display 10 Accounts and will use controller method to get list of accounts.
- AccountView : To view account details. We will just pass account recordId to this component.
- AccountEdit : This will be used to edit or create new record. If we pass recordId to component, then it will update record. If we pass null in recordId then it will create new record.
After saving below code in your org, create App Page from Lightning App Builder section and add "AccountListView" component to it and activate it. After this open this app page and test the functionality.
If your org have recordtypes defined for Account object, then while creating new Account, you will get recordType selection page. No validation have been applied on fields as this is created for demo purpose only.
Below is complete Code:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<aura:component > | |
<aura:attribute name="recordId" type="String" required="true"/> | |
<aura:attribute name="recordInfo" type="Object" access="private"/> | |
<aura:attribute name="record" type="Object" access="private"/> | |
<aura:attribute name="recordError" type="String" access="private"/> | |
<aura:attribute name="currView" type="String" /> | |
<aura:attribute name="accountRecordType" type="String"/> | |
<aura:attribute name="isRecordDeleted" type="boolean" default="false" /> | |
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/> | |
<force:recordData aura:id="recordHandler" recordId="{!v.recordId}" layoutType="FULL" | |
targetFields="{!v.recordInfo}" targetError="{!v.recordError}" mode="EDIT"/> | |
<force:recordData aura:id="newAccountCreator" layoutType="FULL" targetRecord="{!v.record}" targetFields="{!v.recordInfo}" | |
targetError="{!v.recordError}"/> | |
<!-- Display Lightning Data Service errors, if any --> | |
<aura:if isTrue="{!not(empty(v.recordError))}"> | |
<div class="recordError"> | |
<ui:message title="Error" severity="error" closable="true"> | |
{!v.recordError} | |
</ui:message> | |
</div> | |
</aura:if> | |
<!-- Display an editing form --> | |
<div class="slds-form--stacked"> | |
<div class="slds-form-element"> | |
<lightning:input type="text" label="Account Name" value="{!v.recordInfo.Name}" /> | |
</div> | |
<div class="slds-form-element"> | |
<lightning:input type="text" label="Type" value="{!v.recordInfo.Type}" /> | |
</div> | |
<div class="slds-form-element"> | |
<lightning:input type="text" label="Industry" value="{!v.recordInfo.Industry}" /> | |
</div> | |
<div class="slds-form-element"> | |
<lightning:input type="text" label="Phone" value="{!v.recordInfo.Phone}" /> | |
</div> | |
<div class="slds-form-element"> | |
<lightning:button variant="brand" label="Save Record" onclick="{! c.updateRecord }"/> | |
<lightning:button variant="brand" label="Cancel" onclick="{! c.goToView }"/> | |
</div> | |
</div> | |
</aura:component> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
({ | |
doInit: function(component, event, helper) { | |
var accRecordTypeValue = null; | |
if(component.get("v.accountRecordType")){ | |
accRecordTypeValue = component.get("v.accountRecordType"); | |
} | |
if(component.get("v.recordId")=="" || component.get("v.recordId")==null){ | |
// Prepare a new record from template | |
console.log('doinit is called while creating new record remplate'); | |
// Prepare a new record from template | |
component.find("newAccountCreator").getNewRecord( | |
"Account", // sObject type (entityApiName) | |
accRecordTypeValue, // recordTypeId | |
false, // skip cache? | |
$A.getCallback(function() { | |
var rec = component.get("v.record"); | |
var error = component.get("v.recordError"); | |
if(error || (rec === null)) { | |
console.log("Error initializing record template: " + error); | |
return; | |
} | |
console.log("Record template initialized: " + rec.sobjectType); | |
}) | |
); | |
} | |
}, | |
updateRecord: function(component, event, helper) { | |
//console.log(component.find("recordHandler")); | |
if(component.get("v.recordId")!= null){ | |
//alert('update record logic'); | |
component.find("recordHandler").saveRecord($A.getCallback(function(saveResult) { | |
if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") { | |
// Saved! Show a toast UI message | |
// toast supported in lightning experience only | |
console.log('Update record get called from edit page '); | |
var resultsToast = $A.get("e.force:showToast"); | |
console.log('resultsToast value:'+resultsToast); | |
if(resultsToast){ | |
resultsToast.setParams({ | |
"title": "Deleted", | |
"message": "The record is deleted." | |
}); | |
resultsToast.fire(); | |
$A.get("e.force:refreshView").fire(); | |
}else{ | |
component.set("v.isRecordDeleted","true"); | |
console.log('updated record and isRecordDeleted is marked as true'); | |
} | |
} | |
else { | |
var errmsg='Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error); | |
console.log(errmsg); | |
alert(errmsg);} | |
})); | |
}else{ | |
//alert('new record logic'); | |
var selectedRecType=component.get("v.accountRecordType"); | |
//alert('selected recordtype:'+selectedRecType); | |
if(selectedRecType!="" && selectedRecType!=null){ | |
component.set("v.recordInfo.RecordTypeId",selectedRecType); | |
} | |
component.find("newAccountCreator").saveRecord(function(saveResult) { | |
if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") { | |
// Success! Prepare a toast UI message | |
// toast supported in lightning experience only | |
console.log('Update record get called from edit page '); | |
var resultsToast = $A.get("e.force:showToast"); | |
console.log('resultsToast value:'+resultsToast); | |
if(resultsToast){ | |
resultsToast.setParams({ | |
"title": "Deleted", | |
"message": "The record is deleted." | |
}); | |
resultsToast.fire(); | |
$A.get("e.force:refreshView").fire(); | |
}else{ | |
component.set("v.isRecordDeleted","true"); | |
} | |
} | |
else { | |
var errmsg='Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error); | |
console.log(errmsg); | |
alert(errmsg); | |
} | |
}); | |
} | |
}, | |
goToView :function(component, event, helper){ | |
component.set("v.currView","ListView"); | |
} | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<aura:component controller="AccountListViewController" access="global" implements="flexipage:availableForAllPageTypes"> | |
<aura:attribute name="recList" type="List" /> | |
<aura:attribute name="menu" type="List" default="View,Edit,Delete" description="Optional Menu Items"/> | |
<aura:attribute name="currentView" type="String" default="ListView"/> | |
<aura:attribute name="selectedRecord" type="String" /> | |
<aura:attribute name="isRefreshRequired" type="boolean" default="false" /> | |
<aura:handler name="change" value="{!v.isRefreshRequired}" action="{!c.refreshListView}"/> | |
<!--attributes for recordtype selection--> | |
<aura:attribute name="selectedRecordType" type="String"/> | |
<aura:attribute name="recordTypeList" type="Object[]"/> | |
<!--attributes for deleting record from list--> | |
<aura:attribute name="recordDeleteError" type="String" access="private"/> | |
<aura:attribute name="recordIdToDelete" type="String" access="private"/> | |
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/> | |
<!--<aura:handler event="aura:waiting" action="{!c.showSpinner}"/> | |
<aura:handler event="aura:doneWaiting" action="{!c.hideSpinner}"/>--> | |
<aura:attribute name="showSpinner" type="Boolean" default="false" /> | |
<c:showSpinnerCmp show="{!v.showSpinner}"/> | |
<div class="slds-align--absolute-center"> | |
<lightning:button variant="brand" label="Create New" onclick="{!c.createRecordhandler}"/> | |
</div> | |
<!--Section for Account List View starts--> | |
<aura:if isTrue="{!v.currentView =='ListView'}"> | |
<aura:if isTrue="{!v.recList.length > 0}"> | |
<table class="slds-table slds-table--bordered slds-table--cell-buffer"> | |
<thead> | |
<tr class="slds-text-title--caps"> | |
<th scope="col">Actions</th> | |
<th scope="col">Name</th> | |
<th scope="col">Type</th> | |
<th scope="col">Industry</th> | |
<th scope="col">RecordType Name</th> | |
</tr> | |
</thead> | |
<aura:iteration items="{!v.recList}" var="item"> | |
<tr> | |
<td> | |
<lightning:buttonMenu iconName="utility:threedots" > | |
<aura:iteration items="{!v.menu}" var="menuItem"> | |
<lightning:menuItem label="{!menuItem}" value="{!item.Id + '---' + menuItem}" onactive="{!c.onSelectMenuItem}"/> | |
</aura:iteration> | |
</lightning:buttonMenu> | |
</td> | |
<td> {!item.Name}</td> | |
<td> {!item.Type}</td> | |
<td> {!item.Industry}</td> | |
<td>{!item.RecordType.Name}</td> | |
</tr> | |
</aura:iteration> | |
</table> | |
</aura:if> | |
</aura:if> | |
<!--Section for Account List View ends--> | |
<!--Section for Account recordType Selection starts--> | |
<aura:if isTrue="{!v.currentView =='RecordTypeSelection'}"> | |
<div role="dialog" tabindex="-1" class="slds-modal slds-fade-in-open"> | |
<div class="slds-modal__container"> | |
<div class="slds-modal__header"> | |
<lightning:buttonIcon class="slds-modal__close" iconName="utility:close" size="large" | |
variant="bare-inverse" alternativeText="Close" onclick="{!c.defaultCloseAction}" /> | |
<h2 id="header43" class="slds-text-heading--medium">Please select record Type</h2> | |
</div> | |
<div class="slds-modal__content slds-p-around--medium"> | |
<div class="slds-align--absolute-center"> | |
<aura:iteration items="{!v.recordTypeList}" var="item"> | |
<lightning:input aura:id="srd" type="radio" label="{!item.recordTypeLabel}" checked="{!if(v.selectedRecordType==item.recordTypeId,true,false)}" | |
name="accountType" value="{!item.recordTypeId}" onchange="{!c.onChangeRecordType}"/> | |
</aura:iteration> | |
</div> | |
</div> | |
<div class="slds-modal__footer"> | |
<lightning:button label="Cancel" variant="neutral" onclick="{!c.defaultCloseAction}"/> | |
<lightning:button label="Continue" variant="brand" onclick="{!c.onconfirm}"/> | |
</div> | |
</div> | |
</div> | |
<div class="slds-backdrop slds-backdrop--open"></div> | |
</aura:if> | |
<!--Section for Account recordType Selection ends--> | |
<!--Section for Account record View starts--> | |
<aura:if isTrue="{!v.currentView =='RecordView'}"> | |
<div role="dialog" tabindex="-1" class="slds-modal slds-fade-in-open"> | |
<div class="slds-modal__container"> | |
<div class="slds-modal__header"> | |
<lightning:buttonIcon class="slds-modal__close" iconName="utility:close" size="large" | |
variant="bare-inverse" alternativeText="Close" onclick="{!c.defaultCloseAction}" /> | |
<h2 id="header43" class="slds-text-heading--medium">Account Details</h2> | |
</div> | |
<div class="slds-modal__content slds-p-around--medium"> | |
<div class="slds-align--absolute-center"> | |
<c:AccountView recordId="{!v.selectedRecord}" currView="{!v.currentView}" | |
isRecordDeleted="{!v.isRefreshRequired}"/> | |
</div> | |
</div> | |
<div class="slds-modal__footer"> | |
</div> | |
</div> | |
</div> | |
<div class="slds-backdrop slds-backdrop--open"></div> | |
</aura:if> | |
<!--Section for Account record View ends--> | |
<!--Section for Account record edit starts--> | |
<aura:if isTrue="{!v.currentView =='RecordEdit'}"> | |
<div role="dialog" tabindex="-1" class="slds-modal slds-fade-in-open"> | |
<div class="slds-modal__container"> | |
<div class="slds-modal__header"> | |
<lightning:buttonIcon class="slds-modal__close" iconName="utility:close" size="large" | |
variant="bare-inverse" alternativeText="Close" onclick="{!c.defaultCloseAction}" /> | |
<h2 id="header43" class="slds-text-heading--medium">Account Details</h2> | |
</div> | |
<div class="slds-modal__content slds-p-around--medium"> | |
<div class="slds-align--absolute-center"> | |
<c:AccountEdit recordId="{!v.selectedRecord}" currView="{!v.currentView}" | |
accountRecordType="{!v.selectedRecordType}" isRecordDeleted="{!v.isRefreshRequired}"/> | |
</div> | |
</div> | |
<div class="slds-modal__footer"> | |
</div> | |
</div> | |
</div> | |
<div class="slds-backdrop slds-backdrop--open"></div> | |
</aura:if> | |
<!--Section for Account record edit ends--> | |
<!--Section to display prompt before delete starts--> | |
<aura:if isTrue="{!v.currentView =='RecordDeleteConfirm'}"> | |
<force:recordData aura:id="recordDeleteHandler" recordId="{!v.recordIdToDelete}" fields="Id" | |
targetError="{!v.recordDeleteError}" /> | |
<div role="dialog" tabindex="-1" class="slds-modal slds-fade-in-open"> | |
<div class="slds-modal__container"> | |
<div class="slds-modal__header"> | |
<h2 id="header43" class="slds-text-heading--medium">Confirmation</h2> | |
</div> | |
<div class="slds-modal__content slds-p-around--medium"> | |
<div class="slds-align--absolute-center"> | |
Are you sure want to delete account? | |
</div> | |
</div> | |
<div class="slds-modal__footer"> | |
<lightning:button label="Cancel" variant="neutral" onclick="{!c.defaultCloseAction}"/> | |
<lightning:button label="Confirm" variant="brand" onclick="{!c.confirmDelete}"/> | |
</div> | |
</div> | |
</div> | |
<div class="slds-backdrop slds-backdrop--open"></div> | |
</aura:if> | |
<!--Section to display prompt before delete ends--> | |
</aura:component> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class AccountListViewController { | |
@auraEnabled | |
public static List<Account> findRecords(){ | |
List<Account> returnList=new List<Account>(); | |
returnList=[select id,name,type,industry,RecordType.Name,RecordTypeId from Account order by LastModifiedDate DESC Limit 10]; | |
return returnList; | |
} | |
@AuraEnabled | |
public static string findRecordTypes(){ | |
string returnString=''; | |
List<RecordType> recordList = new List<RecordType> (); | |
recordList= [Select id, name from RecordType where sobjectType ='Account' and IsActive=true]; | |
List<RecordTypeWrapper> wrapperList=new List<RecordTypeWrapper>(); | |
for(RecordType sb : recordList) { | |
RecordTypeWrapper rw=new RecordTypeWrapper(); | |
rw.recordTypeLabel=sb.name; | |
rw.recordTypeId=sb.id; | |
wrapperList.add(rw); | |
} | |
if(wrapperList.size()>0){ | |
returnString= JSON.serialize(wrapperList); | |
} | |
system.debug('*****'+returnString); | |
return returnString; | |
} | |
public class RecordTypeWrapper{ | |
public string recordTypeLabel{get;set;} | |
public string recordTypeId{get;set;} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
({ | |
doInit : function(component, event, helper){ | |
var params ={}; | |
helper.callServer( | |
component, | |
"c.findRecords", | |
function(response){ | |
component.set("v.recList",response); | |
}, | |
params | |
); | |
}, | |
confirmDelete : function(component, event, helper){ | |
var selectedId =component.get("v.selectedRecord"); | |
component.set("v.recordIdToDelete",selectedId); | |
console.log('*******recordIdToDelete:'+component.get("v.selectedRecord")); | |
component.find("recordDeleteHandler").deleteRecord($A.getCallback(function(saveResult) { | |
if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") { | |
// Deleted! Show a toast UI message | |
// toast supported in lightning experience only | |
console.log('Delete is successfull'); | |
var resultsToast = $A.get("e.force:showToast"); | |
if(resultsToast){ | |
resultsToast.setParams({ | |
"title": "Deleted", | |
"message": "The record is deleted." | |
}); | |
resultsToast.fire(); | |
$A.get("e.force:refreshView").fire(); | |
}else{ | |
console.log(' Refreshing list view'); | |
//refresh list view | |
var params ={}; | |
helper.callServer( | |
component, | |
"c.findRecords", | |
function(response){ | |
component.set("v.recList",response); | |
component.set("v.currentView","ListView"); | |
}, | |
params | |
); | |
} | |
}else { | |
var errmsg='Unknown problem, state: ' + saveResult.state +', error: ' + JSON.stringify(saveResult.error); | |
console.log(errmsg); | |
alert(errmsg); | |
} | |
})); | |
}, | |
onSelectMenuItem : function(component, event, helper) { | |
var selectedOption = event.getSource().get('v.value'); | |
var selectedId = selectedOption.split('---')[0]; | |
//alert('*************selectedId:'+selectedId+':selected action:'+selectedOption); | |
component.set("v.selectedRecord",selectedId); | |
//console.log(event.getSource()); | |
if (selectedOption.endsWith("Delete")) { | |
component.set("v.recordIdToDelete",selectedId); | |
console.log('record id to delete:'+component.get("v.recordIdToDelete")); | |
component.set("v.currentView","RecordDeleteConfirm"); | |
}else if(selectedOption.endsWith("View")){ | |
component.set("v.currentView","RecordView"); | |
}else if(selectedOption.endsWith("Edit")){ | |
component.set("v.currentView","RecordEdit"); | |
} | |
}, | |
showSpinner: function(component, event, helper) { | |
var spinner = component.find("spinner"); | |
$A.util.removeClass(spinner, "slds-hide"); | |
}, | |
hideSpinner: function(component, event, helper) { | |
//alert('hideSpinner'); | |
var spinner = component.find("spinner"); | |
$A.util.addClass(spinner, "slds-hide"); | |
}, | |
createRecordhandler : function(component, event, helper){ | |
component.set("v.selectedRecord",null); | |
//component.set("v.selectedRecord",""); | |
//if you pass blank value, then you will get error saying record is either deleted or doesnot exist. specify null | |
//Call to server to find out if recordType exist for Account | |
var params ={}; | |
helper.callServer( | |
component, | |
"c.findRecordTypes", | |
function(response){ | |
//alert('Response from controller for recordtypes:'+JSON.stringify(response)); | |
if(response!=''){ | |
var jsonObject=JSON.parse(response); | |
component.set("v.recordTypeList",jsonObject); | |
component.set('v.selectedRecordType',jsonObject[0].recordTypeId); | |
//component.find("srd").set("v.value",jsonObject[0].recordTypeId); | |
if(jsonObject.length >1){ | |
//alert('more than 2 record type'); | |
component.set("v.currentView","RecordTypeSelection"); | |
}else{ | |
//alert('only 1 record type'); | |
component.set("v.currentView","RecordEdit"); | |
} | |
}else{ | |
//alert('RecordType doesnot exist'); | |
component.set('v.selectedRecordType',null); | |
component.set("v.currentView","RecordEdit"); | |
} | |
}, | |
params | |
); | |
}, | |
defaultCloseAction : function(component, event, helper) { | |
$A.util.addClass(component, "slds-hide"); | |
component.set("v.currentView","ListView"); | |
}, | |
onconfirm : function(component, event, helper){ | |
//alert('confirm get called'); | |
var selectedRecType=component.get("v.selectedRecordType"); | |
component.set("v.currentView","RecordEdit"); | |
}, | |
onChangeRecordType : function(component, event,helper){ | |
var recordTypeValue = event.getSource().get("v.value"); | |
component.set('v.selectedRecordType', recordTypeValue); | |
}, | |
refreshListView : function(component,event,helper){ | |
console.log('isRefreshRequired value:'+ component.get("v.isRefreshRequired")); | |
if(component.get("v.isRefreshRequired") == "true"){ | |
console.log('******List view is getting refreshed'); | |
//refresh list view | |
var params ={}; | |
helper.callServer( | |
component, | |
"c.findRecords", | |
function(response){ | |
component.set("v.recList",response); | |
component.set("v.currentView","ListView"); | |
}, | |
params | |
); | |
} | |
component.set("v.isRefreshRequired","false"); | |
} | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
({ | |
callServer : function(component, method, callback, params) { | |
//alert('Calling helper callServer function'); | |
component.set("v.showSpinner",true); | |
var action = component.get(method); | |
if(params){ | |
action.setParams(params); | |
} | |
action.setCallback(this, function(response) { | |
var state = response.getState(); | |
if (state === "SUCCESS") { | |
callback.call(this,response.getReturnValue()); | |
}else if(state === "ERROR"){ | |
alert('Problem with connection. Please try again.'); | |
} | |
component.set("v.showSpinner",false); | |
}); | |
$A.enqueueAction(action); | |
} | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<aura:component > | |
<aura:attribute name="recordId" type="String" required="true"/> | |
<aura:attribute name="recordInfo" type="Object"/> | |
<aura:attribute name="recordError" type="String"/> | |
<aura:attribute name="currView" type="String" /> | |
<aura:attribute name="isRecordDeleted" type="boolean" default="false" /> | |
<force:recordData aura:id="recordLoader" recordId="{!v.recordId}" layoutType="FULL" | |
targetFields="{!v.recordInfo}" targetError="{!v.recordError}"/> | |
<div class="slds-form--stacked"> | |
<div class="slds-form-element"> | |
<label class="slds-form-element__label" for="recordName">Name </label> | |
<div class="slds-form-element__control"> | |
<ui:outputText value="{!v.recordInfo.Name}" aura:id="recordName"/> | |
</div> | |
</div> | |
<div class="slds-form-element"> | |
<label class="slds-form-element__label" for="recordOwnerName">Owner </label> | |
<div class="slds-form-element__control"> | |
<ui:outputText value="{!v.recordInfo.Owner.Name}" aura:id="recordOwnerName"/> | |
</div> | |
</div> | |
<div class="slds-form-element"> | |
<label class="slds-form-element__label" for="accType">Type </label> | |
<div class="slds-form-element__control"> | |
<ui:outputText value="{!v.recordInfo.Type}" aura:id="accType"/> | |
</div> | |
</div> | |
<div class="slds-form-element"> | |
<label class="slds-form-element__label" for="accIndustry">Industry </label> | |
<div class="slds-form-element__control"> | |
<ui:outputText value="{!v.recordInfo.Industry}" aura:id="accIndustry"/> | |
</div> | |
</div> | |
<div class="slds-form-element"> | |
<lightning:button variant="brand" label="Edit Record" onclick="{!c.editRecordHandler}"/> | |
<lightning:button variant="brand" label="Delete Record" onclick="{!c.deleteRecordHandler}"/> | |
<lightning:button variant="brand" label="Back To List View" onclick="{!c.goBack}"/> | |
</div> | |
</div> | |
<!-- Display Lightning Data Service errors, if any --> | |
<aura:if isTrue="{!not(empty(v.recordError))}"> | |
<div class="recordError"> | |
<ui:message title="Error" severity="error" closable="true"> | |
{!v.recordError} | |
</ui:message> | |
</div> | |
</aura:if> | |
</aura:component> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
({ | |
editRecordHandler : function(component, event, helper) { | |
component.set("v.currView","RecordEdit"); | |
//alert('editRecordHandler called'); | |
}, | |
goBack : function (component, event, helper){ | |
// Reload the view so components | |
component.set("v.currView","ListView"); | |
}, | |
deleteRecordHandler: function(component, event, helper) { | |
component.find("recordLoader").deleteRecord($A.getCallback(function(saveResult) { | |
if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") { | |
// Deleted! Show a toast UI message | |
// toast supported in lightning experience only | |
console.log('Record delete from View page get called'); | |
var resultsToast = $A.get("e.force:showToast"); | |
console.log('resultsToast value:'+resultsToast); | |
if(resultsToast){ | |
resultsToast.setParams({ | |
"title": "Deleted", | |
"message": "The record is deleted." | |
}); | |
resultsToast.fire(); | |
$A.get("e.force:refreshView").fire(); | |
}else{ | |
component.set("v.isRecordDeleted","true"); | |
} | |
} | |
else { | |
var errmsg='Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error); | |
console.log(errmsg); | |
alert(errmsg); | |
} | |
})); | |
} | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<aura:application extends="force:slds"> | |
<c:AccountListView /> | |
</aura:application> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<aura:component > | |
<aura:attribute name="show" type="Boolean" default="false" /> | |
<aura:handler name="change" value="{!v.show}" action="{!c.spinnerDisplayHandler}"/> | |
<div class="slds-align--absolute-center"> | |
<lightning:spinner aura:id="spinner" variant="brand" size="large" class="slds=hide"/> | |
</div> | |
</aura:component> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
({ | |
spinnerDisplayHandler : function(component, event, helper) { | |
console.log('show spinner value changes'); | |
helper.showHideSpinner(component); | |
} | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
({ | |
showHideSpinner : function(component) { | |
var showValue = component.get('v.show'); | |
if(showValue) { | |
console.log('showValue'+showValue); | |
var spinner = component.find("spinner"); | |
console.log('spinner'+spinner); | |
$A.util.removeClass(spinner, "slds-hide"); | |
} else { | |
console.log('showValue'+showValue); | |
var spinner = component.find("spinner"); | |
console.log('spinner'+spinner); | |
$A.util.addClass(spinner, "slds-hide"); | |
} | |
} | |
}) |
Looking forward for everyone's comments and feedback!!!!!
Changes to Lightning Data Services (LDS) in Summer'17 Release
Changes to Lightning Data Services (LDS) in Summer'17 Release
More Blogs>>:
DYNAMICALLY CREATING AND DESTROYING LIGHTNING COMPONENTS
RAISING AND HANDLING CUSTOM EVENTS IN sALESFORCE lIGHTNING
WHY TO USE DESIGN RESOURCE AND HOW TO ADD DYNAMIC OPTION TO DATASOURCE
PASSING INNER WRAPPER CLASS TO LIGHTNING COMPONENT
LIGHTNING COMPONENT FOR RECORDTYPE SELECTION FOR ANY SOBJECT
Thansk for the code.
ReplyDeleteI have this error:
Action failed: c:AccountListView$controller$doInit [helper.callServer is not a function. (In 'helper.callServer', 'helper.callServer' is undefined)] doInit()@https://mikelightning-dev-ed.lightning.force.com/auraFW/resources/ZCuyRUYzK_kAf4cKCIeS2A/lockerservice/safeEval.html:11:26 _createComponent()@https://mikelightning-dev-ed.lightning.force.com/auraFW/resources/ZCuyRUYzK_kAf4cKCIeS2A/lockerservice/safeEval.html:6:23 createComponent()@https://mikelightning-dev-ed.lightning.force.com/auraFW/resources/ZCuyRUYzK_kAf4cKCIeS2A/lockerservice/safeEval.html:104:55 {anonymous}()@https://mikelightning-dev-ed.lightning.force.com/auraFW/resources/ZCuyRUYzK_kAf4cKCIeS2A/lockerservice/safeEval.html:54:41
Hi Miguel,
ReplyDeleteActually AccountListViewHelper.js file was missing in sample code.
I have added AccountListViewHelper.js code. After including this code, you will not get above error.
Thanks,
Sunil Kumar
Hi Sunil,
ReplyDeleteit is running well.
Thanks for the code share.
I found your this post while searching for some related information on blog search...Its a good post..keep posting and update the information. odzyskiwanie danych z uszkodzonego telefonu
ReplyDeleteThanks for this Great Information.
ReplyDeleteFor additional info, if you need The Best AC Rental Service in Indonesia for something like event or anything elese, you can try to reach us. We will be very happy to assist you.
Thanks again.
I wanted to thank you for this great read!! I definitely enjoying every little bit of it I have you bookmarked to check out new stuff you post. for more info
ReplyDeleteTook me time to read all the comments, but I really enjoyed the article. It proved to be Very helpful to me and I am sure to all the commenters here! It’s always nice when you can not only be informed, but also entertained! Plombier Paris
ReplyDeleteI think that thanks for the valuabe information and insights you have so provided here. alkomprar tienda on line
ReplyDeleteSuch a wonderful blog! This is really superb and thanks for your sharing with us...
ReplyDeletecontract dispute resolution process
contract dispute settlement agreement