The lightning:record*Form and force:recordData components are the easiest way to work with records. They are built on top of Lightning Data Service, which manages field-level security and sharing for you in addition to managing data loading and refresh. You can use these components for objects that are supported by User Interface API
Use Apex only if you’re working with a scenario listed at Using Apex, You can call the Apex method imperatively, such as in response to a button click, as shown in the Loading Record Data from a Standard Object section. Alternatively, to load record data during component initialization, use the init handler, as shown in the Loading Record Data By Criteria section. When using Apex to load or provision data, you must handle data refresh on your own by invoking the Apex method again.
Retrieving Data from an Object
Fetch records from an object using an Apex controller. The provided Apex controller contains functions that retrieve a list of tasks. Tasks are objects that are not compatible with Lightning Data Service or the User Interface API. Hence, it is advisable to utilize Apex for loading task record data.
public with sharing class TaskController { @AuraEnabled(cacheable=true) public static List<Task> getTasks() { return [SELECT Subject, Priority, Status FROM Task]; } }
This example component uses the previous Apex controller to display a list of task record data when you press a button. The flexipage:availableForAllPageTypes interface denotes that you can use this example on a Lightning page.
<!-- apexForTasks.cmp --> <aura:component implements="flexipage:availableForAllPageTypes" controller="TaskController"> <aura:attribute name="tasks" type="Task[]"/> <lightning:card iconName="standard:task"> <lightning:button label="Get Tasks" onclick="{!c.getMyTasks}"/> <aura:iteration var="task" items="{!v.tasks}"> <p>{!task.Subject} : {!task.Priority}, {!task.Status}</p> </aura:iteration> </lightning:card> </aura:component>
When you press the button, the following client-side controller calls the getTasks() method and sets the tasks attribute on the component. For more information about calling server-side controller methods, see Calling a Server-Side Action.
// apexForTasksController.js ({ getMyTasks: function(cmp){ var action = cmp.get("c.getTasks"); action.setCallback(this, function(response){ var state = response.getState(); if (state === "SUCCESS") { cmp.set("v.tasks", response.getReturnValue()); } }); $A.enqueueAction(action); } })
Retrieving Data Records Based on Criteria
As we’ve learned, to load a simple list of record data, you can use base components or force:recordData, as shown at Loading a Record. But to use a SOQL query to select certain records, use an Apex controller.
Remember that the method must be static, and global or public. The method must be decorated with @AuraEnabled(cacheable=true).
For example, query related cases based on an account Id and limit the result to 10 records.
public with sharing class CaseController { @AuraEnabled(cacheable=true) public static List<Case> getCases(String accountId) { return [SELECT AccountId, Id, Subject, Status, Priority, CaseNumber FROM Case WHERE AccountId = :accountId LIMIT 10]; } }
The client-side controller loads related cases using the init handler. The action.setParams() method passes in the record Id of the account record being viewed to the Apex controller,
// casesForAccountController.js ({ init : function(cmp, evt) { var action = cmp.get("c.getCases"); action.setParams({ "accountId": cmp.get("v.recordId") }); action.setCallback(this, function(response){ var state = response.getState(); if (state === "SUCCESS") { cmp.set("v.cases", response.getReturnValue()); } }); $A.enqueueAction(action); } })
In your custom component, load a form that enables editing and updating of cases on an account record using lightning:recordEditForm, by performing these steps.
- Query the relevant cases and set the result to the component attribute v.cases.
- Iterate over the cases by passing in the case Id to the recordId attribute on lightning:recordEditForm.
The example implements the flexipage:availableForRecordHome and force:hasRecordId interfaces so you can use the example on an account record page.
<!-- casesForAccount.cmp --> <aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" controller="CaseController"> <aura:attribute name="cases" type="Case[]"/> <aura:attribute name="recordId" type="Id" /> <aura:handler name="init" value="{! this }" action="{! c.init }"/> <aura:iteration items="{!v.cases}" var="case"> <lightning:card title="{!case.Id}" iconName="standard:case"> <lightning:recordEditForm objectApiName="Case" recordId="{!case.Id}"> <lightning:inputField fieldName="Subject"/> <lightning:inputField fieldName="Status"/> <!– Read-only field --> <lightning:outputField fieldName="Origin" variant="label-hidden"/> <lightning:button label="Update case" type="submit"/> </lightning:recordEditForm> </lightning:card> </aura:iteration> </aura:component>
Note
The case data on the account record is managed by Lightning Data Service since it uses lightning:recordEditForm; therefore, the case data that’s referenced (subject, status, and origin) reflects the latest data. However, if a case on the account is deleted or a new case is added to the account, you must invoke the Apex method again to query the new results.
For read-only data, use lightning:outputField. To work with read-only data only, use lightning:recordViewForm or lightning:recordForm. For granular control of your UI, use force:recordData. For more information, see Lightning Data Service.