LDS Theory and Examples
LDS Theory and Examples
Eliminates apex controller and still can perform CRUD operation. It’s like Standard Controllers in
VF page.
Enable progressive record loading, caching, and merging more fields and layouts into the cache
Promote consistency by using only one instance of the record data across multiple components
If you have a Lightning application that creates, reads, updates, or deletes records then LDS is the best
and most efficient way to do CRUD operations.
https://trailhead.salesforce.com/content/learn/modules/lightning_data_service/
lightning_data_service_manipulate_records
<lightning:recordForm
recordId="001xcxxxxxxxxxx"
objectApiName="Account"
layoutType="Compact"
mode="view"
columns="2"/>
<lightning:recordForm
recordId="{!v.recordId}"
objectApiName="Account"
layoutType="Compact"
mode="view"
columns="2"/>
({
handleSubmit : function(cmp, event, helper) {
event.preventDefault(); // stop the form from submitting
const fields = event.getParam('fields');
fields.LastName = 'My Custom Last Name'; // modify a field
cmp.find('myRecordForm').submit(fields);
}
})
<aura:component
implements="flexipage:availableForRecordHome,force:hasRecordId"
access="global" >
<aura:attribute name="fields" type="String[]"
default="['Name','AnnualRevenue','Industry']" />
<aura:attribute name="recordId" type="String"/>
<lightning:notificationsLibrary aura:id="notifLib"/>
<lightning:recordForm
objectApiName="Account"
fields="{!v.fields}"
onsuccess="{!c.handleSuccess}" />
</aura:component>
({
handleSuccess : function(component, event, helper) {
component.find('notifLib').showToast({
"variant": "success",
"title": "Account Created",
"message": "Record ID: " + event.getParam("id")
});
}
})
Pre-population of field value is not supported.
compact or comfy density can be set to show labels next to value or on top of
the value respectively.
Record Edit Form (lightning:recordEditForm)
<aura:component>
<lightning:recordEditForm recordId="" objectApiName="Contact">
<lightning:messages />
<lightning:outputField fieldName="AccountId" />
<lightning:inputField fieldName="FirstName" value="Ramesh"/>
<lightning:inputField fieldName="LastName" />
<lightning:inputField fieldName="Email" />
<lightning:button class="slds-m-top_small" variant="brand"
type="submit" name="update" label="Update" />
</lightning:recordEditForm>
</aura:component>
<aura:component>
<lightning:recordEditForm aura:id="recordEditForm"
objectApiName="Contact">
<lightning:messages />
<lightning:inputField fieldName="Name" />
<lightning:button class="slds-m-top_small" type="submit"
label="Create new" />
</lightning:recordEditForm>
</aura:component>
<aura:component>
<lightning:recordEditForm
objectApiName="Account"
onload="{!c.handleCreateLoad}">
<lightning:messages />
<lightning:inputField aura:id="nameField" fieldName="Name"/>
<lightning:button class="slds-m-top_small" type="submit" label="Create
new" />
</lightning:recordEditForm>
({
handleCreateLoad: function (cmp, event, helper) {
var nameFieldValue = cmp.find("nameField").set("v.value", "My New
Account");
}
})
<aura:component>
<aura:attribute name="disabled" type="Boolean" default="false" />
<aura:attribute name="saved" type="Boolean" default="false" />
<aura:attribute name="showSpinner" type="Boolean" default="false" />
<aura:if isTrue="{!v.showSpinner}">
<lightning:spinner />
</aura:if>
<aura:if isTrue="{!!v.saved}">
<lightning:recordEditForm
onload="{!c.handleLoad}"
onsubmit="{!c.handleSubmit}"
onsuccess="{!c.handleSuccess}"
recordId="{!v.recordId}"
objectApiName="Bad_Guy__c">
<!-- the messages component is for error messages -->
<lightning:messages />
</aura:component>
Record View Form (lightning:recordViewForm)
<aura:component>
<lightning:recordViewForm recordId="001XXXXXXXXXXXXXXX"
objectApiName="My_Contact__c">
<div class="slds-box">
<lightning:outputField fieldName="Name" />
<lightning:outputField fieldName="Email__c" />
</div>
</lightning:recordViewForm>
</aura:component>
Record Data(force:recordData)
<aura:component implements="flexipage:availableForRecordHome,
force:lightningQuickActionWithoutHeader, force:hasRecordId">
<force:recordData aura:id="recordLoader"
recordId="{!v.recordId}"
targetFields="{!v.simpleRecord}"
targetError="{!v.recordError}"
recordUpdated="{!c.handleRecordUpdated}"
/>
<!-- Display a lightning card with details about the record -->
<div class="Record Details">
<lightning:card iconName="standard:account" title="{!
v.simpleRecord.Name}" >
<div class="slds-p-horizontal--small">
<p class="slds-text-heading--small">
<lightning:formattedText title="Billing City" value="{!
v.simpleRecord.BillingCity}" /></p>
<p class="slds-text-heading--small">
<lightning:formattedText title="Billing State" value="{!
v.simpleRecord.BillingState}" /></p>
</div>
</lightning:card>
</div>
({
handleRecordUpdated: function(component, event, helper) {
var eventParams = event.getParams();
if(eventParams.changeType === "LOADED") {
// record is loaded (render other component which needs record
data value)
console.log("Record is loaded successfully.");
console.log("You loaded a record in " +
component.get("v.simpleRecord.Industry"));
} else if(eventParams.changeType === "CHANGED") {
// record is changed
} else if(eventParams.changeType === "REMOVED") {
// record is deleted
} else if(eventParams.changeType === "ERROR") {
// there’s an error while loading, saving, or deleting the record
}
}
})
<aura:component
implements="flexipage:availableForRecordHome,force:hasRecordId">
<force:recordData aura:id="recordHandler"
recordId="{!v.recordId}"
layoutType="FULL"
targetRecord="{!v.record}"
targetFields="{!v.simpleRecord}"
targetError="{!v.recordError}"
mode="EDIT"
recordUpdated="{!c.handleRecordUpdated}"
/>
<!-- Display a lightning card with details about the record -->
<div class="Record Details">
<lightning:card iconName="standard:account" title="{!
v.simpleRecord.Name}" >
<div class="slds-p-horizontal--small">
<p class="slds-text-heading--small">
<lightning:formattedText title="Billing State" value="{!
v.simpleRecord.BillingState}" /></p>
<p class="slds-text-heading--small">
<lightning:formattedText title="Billing City" value="{!
v.simpleRecord.BillingCity}" /></p>
</div>
</lightning:card>
</div>
({
handleSaveRecord: function(component, event, helper) {
component.find("recordHandler").saveRecord($A.getCallback(function(saveResult
) {
// use the recordUpdated event handler to handle generic logic
when record is changed
if (saveResult.state === "SUCCESS" || saveResult.state ===
"DRAFT") {
// handle component related logic in event handler
} else if (saveResult.state === "INCOMPLETE") {
console.log("User is offline, device doesn't support
drafts.");
} else if (saveResult.state === "ERROR") {
console.log('Problem saving record, error: ' +
JSON.stringify(saveResult.error));
} else {
console.log('Unknown problem, state: ' + saveResult.state +
', error: ' + JSON.stringify(saveResult.error));
}
}));
},
/**
* Control the component behavior here when record is changed (via any
component)
*/
handleRecordUpdated: function(component, event, helper) {
var eventParams = event.getParams();
if(eventParams.changeType === "CHANGED") {
// get the fields that changed for this record
var changedFields = eventParams.changedFields;
console.log('Fields that are changed: ' +
JSON.stringify(changedFields));
// record is changed, so refresh the component (or other
component logic)
var resultsToast = $A.get("e.force:showToast");
resultsToast.setParams({
"title": "Saved",
"message": "The record was updated."
});
resultsToast.fire();
<force:recordData aura:id="recordHandler"
recordId="{!v.recordId}"
fields="Id"
targetError="{!v.recordError}"
recordUpdated="{!c.handleRecordUpdated}" />
({
handleDeleteRecord: function(component, event, helper) {
component.find("recordHandler").deleteRecord($A.getCallback(function(deleteRe
sult) {
// NOTE: If you want a specific behavior(an action or UI
behavior) when this action is successful
// then handle that in a callback (generic logic when record is
changed should be handled in recordUpdated event handler)
if (deleteResult.state === "SUCCESS" || deleteResult.state ===
"DRAFT") {
// record is deleted
console.log("Record is deleted.");
} else if (deleteResult.state === "INCOMPLETE") {
console.log("User is offline, device doesn't support
drafts.");
} else if (deleteResult.state === "ERROR") {
console.log('Problem deleting record, error: ' +
JSON.stringify(deleteResult.error));
} else {
console.log('Unknown problem, state: ' + deleteResult.state +
', error: ' + JSON.stringify(deleteResult.error));
}
}));
},
/**
* Control the component behavior here when record is changed (via any
component)
*/
handleRecordUpdated: function(component, event, helper) {
var eventParams = event.getParams();
if(eventParams.changeType === "CHANGED") {
// record is changed
} else if(eventParams.changeType === "LOADED") {
// record is loaded in the cache
} else if(eventParams.changeType === "REMOVED") {
// record is deleted, show a toast UI message
var resultsToast = $A.get("e.force:showToast");
resultsToast.setParams({
"title": "Deleted",
"message": "The record was deleted."
});
resultsToast.fire();
Methods
NAME ARGUMENTS ACCESS DESCRIPTION
Callback function to be
unknow
callback invoked after new record
n
template is retrieved.
Force a trip to the server, Performs the same load function as on init
skipCache boolean
reloadRecord skipping any local cache. global (recordId, layoutType, mode, etc) but does
required.
unknow Callback function to be invoked
callback
n after record is retrieved.
1. Can be operated only on one record at a time. Can’t handle many records at a time.
2. One operation at a time. Multiple operations are not possible.
3. Doesn’t support all the objects. Ex – Task, Event etc. are not supported.
4. Lightning Data Service supports spanned fields with a maximum depth of five levels
5. Not supportive/available everywhere like classic and all.