学习目标
完成本单元后,您将能够:
- 使用闪电数据服务创建,读取,上传和删除记录。
- 构建一个使用force的组件:recordData。
- 解释Lightning Data Service如何缓存记录。
使用force … recordData标签
在最后一个单元中,我们介绍了Lightning Data Service提供的漂亮的性能升级和生活质量功能。现在让我们学习如何使用它们。
请记住,force:recordData本身不包含任何UI元素。 force:recordData标签只是用来与服务器通信并管理本地缓存的逻辑。为了让用户查看和修改由LDS获取的数据,您必须包含UI元素。 force:recordData标记使用UI API向您的UI组件提供数据。
加载记录
你做的第一件事是为你的UI组件创建一个记录,就是加载它。通过在指定recordId,mode和layoutType或fields属性的同时在组件中包含force:recordData来加载记录。
<aura:component implements="flexipage:availableForRecordHome, force:hasRecordId"> <!--inherit recordId attribute-->
<aura:attribute name="record" type="Object"
description="The record object to be displayed"/>
<aura:attribute name="simpleRecord" type="Object"
description="A simplified view record object to be displayed"/>
<aura:attribute name="recordError" type="String"
description="An error message bound to force:recordData"/>
<force:recordData aura:id="record"
layoutType="FULL"
recordId="{!v.recordId}"
targetError="{!v.recordError}"
targetRecord="{!v.record}"
targetFields ="{!v.simpleRecord}"
mode="VIEW"/>
<!-- 显示有关记录详情的闪电卡 -->
<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>
<!-- 显示闪电数据服务错误,如果有的话 -->
<aura:if isTrue="{!not(empty(v.recordError))}">
<div class="recordError">
{!v.recordError}</div>
</aura:if>
</aura:component>
保存记录
LDS的神奇之处在于,在Lightning应用程序中有多个组件可以从相同的记录数据中提取。这些组件中的一部分只是显示记录数据,而其他组件则可以操纵数据本身。该组件加载记录以及一个简短的表单,用户可以在其中输入记录的新名称。
<aura:component implements="flexipage:availableForRecordHome, force:hasRecordId"> <!--inherit recordId attribute-->
<aura:attribute name="record" type="Object" />
<aura:attribute name="simpleRecord" type="Object" />
<aura:attribute name="recordError" type="String" />
<force:recordData aura:id="recordEditor"
layoutType="FULL"
recordId="{!v.recordId}"
targetError="{!v.recordError}"
targetRecord="{!v.record}"
targetFields ="{!v.simpleRecord}"
mode="EDIT" />
<!-- 显示有关记录详情的闪电卡 -->
<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>
<br/>
<!-- 显示编辑表格 -->
<div class="Record Details">
<lightning:card iconName="action:edit" title="Edit Account">
<div class="slds-p-horizontal--small">
<lightning:input label="Account Name" value="{!v.simpleRecord.Name}"/>
<br/>
<lightning:button label="Save Account" variant="brand" onclick="{!c.handleSaveRecord}" />
</div>
</lightning:card>
</div>
<!-- 显示闪电数据服务错误,如果有的话 -->
<aura:if isTrue="{!not(empty(v.recordError))}">
<div class="recordError">
{!v.recordError}</div>
</aura:if>
</aura:component>
({
handleSaveRecord: function(component, event, helper) {
component.find("recordEditor").saveRecord($A.getCallback(function(saveResult) {
if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
console.log("保存成功完成");
} else if (saveResult.state === "INCOMPLETE") {
console.log("用户离线,设备不支持草稿.");
} else if (saveResult.state === "ERROR") {
console.log('问题保存记录,错误:' +
JSON.stringify(saveResult.error));
} else {
console.log('Unknown problem, state: ' + saveResult.state + ', error: ' + JSON.stringify(saveResult.error));
}
}));}
})
好,现在我们来处理其余的CRUD。
Creating Records
要创建一个空记录,请保持recordId属性有效:recordData undefined。
<aura:component implements="flexipage:availableForRecordHome, force:hasRecordId">
<aura:attribute name="newContact" type="Object"/>
<aura:attribute name="simpleNewContact" type="Object"/>
<aura:attribute name="newContactError" type="String"/>
<force:recordData aura:id="contactRecordCreator"
layoutType="FULL"
targetRecord="{!v.newContact}"
targetFields ="{!v.simpleNewContact}"
targetError="{!v.newContactError}"
/>
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<!-- 显示新的联系表格 -->
<div class="Create Contact">
<lightning:card iconName="action:new_contact" title="Create Contact">
<div class="slds-p-horizontal--small">
<lightning:input aura:id="contactField" label="First Name" value="{!v.simpleNewContact.FirstName}"/>
<lightning:input aura:id="contactField" label="Last Name" value="{!v.simpleNewContact.LastName}"/>
<lightning:input aura:id="contactField" label="Title" value="{!v.simpleNewContact.Title}"/>
<br/>
<lightning:button label="Save Contact" variant="brand" onclick="{!c.handleSaveContact}"/>
</div>
</lightning:card>
</div>
<!-- 显示闪电数据服务错误 -->
<aura:if isTrue="{!not(empty(v.newContactError))}">
<div class="recordError">
{!v.recordError}</div>
</aura:if>
</aura:component>
({
doInit: function(component, event, helper) {
// 从模板准备一个新的记录
component.find("contactRecordCreator").getNewRecord(
"Contact", // sObject type (entityAPIName)
null, // recordTypeId
false, // skip cache?
$A.getCallback(function() {
var rec = component.get("v.newContact");
var error = component.get("v.newContactError");
if(error || (rec === null)) {
console.log("错误初始化记录模板:" + error);
}
else {
console.log("Record template initialized: " + rec.sobjectType);
}
})
);
},
handleSaveContact: function(component, event, helper) {
if(helper.validateContactForm(component)) {
component.set("v.simpleNewContact.AccountId", component.get("v.recordId"));
component.find("contactRecordCreator").saveRecord(function(saveResult) {
if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
// 记录已成功保存
var resultsToast = $A.get("e.force:showToast");
resultsToast.setParams({
"title": "Saved",
"message": "The record was saved."
});
resultsToast.fire();
} else if (saveResult.state === "INCOMPLETE") {
// 处理不完整的状态
console.log("用户离线,设备不支持草稿");
} else if (saveResult.state === "ERROR") {
// 处理错误状态
console.log('问题保存联系,错误: ' +
JSON.stringify(saveResult.error));
} else {
console.log('未知问题,状态:' + saveResult.state +
', error: ' + JSON.stringify(saveResult.error));
}
});
}
}
})
({
validateContactForm: function(component) {
var validContact = true;
// 如果必填字段为空,则显示错误消息
var allValid = component.find('contactField').reduce(function (validFields, inputCmp) {
inputCmp.showHelpMessageIfInvalid();
return validFields && inputCmp.get('v.validity').valid;
}, true);
if (allValid) {
// 验证我们有一个帐户附加到
var account = component.get("v.newContact");
if($A.util.isEmpty(account)) {
validContact = false;
console.log("Quick action context doesn't have a valid account.");
}
return(validContact);
}
}
})
删除记录
最后,要删除一条记录,至少指定字段属性设置为“Id”的recordId。
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId">
<aura:attribute name="recordError" type="String" access="private"/>
<force:recordData aura:id="recordHandler"
recordId="{!v.recordId}"
fields="Id"
targetError="{!v.recordError}"
/>
<!-- 显示删除记录表格 -->
<div class="Delete Record">
<lightning:card iconName="action:delete" title="Delete Record">
<div class="slds-p-horizontal--small">
<lightning:button label="Delete Record" variant="destructive" onclick="{!c.handleDeleteRecord}"/>
</div>
</lightning:card>
</div>
<!-- 显示闪电数据服务错误,如果有的话 -->
<aura:if isTrue="{!not(empty(v.recordError))}">
<div class="recordError">
{!v.recordError}</div>
</aura:if>
</aura:component>
({
handleDeleteRecord: function(component, event, helper) {
component.find("recordHandler").deleteRecord($A.getCallback(function(deleteResult) {
if (deleteResult.state === "SUCCESS" || deleteResult.state === "DRAFT") {
console.log("Record is deleted.");
var resultsToast = $A.get("e.force:showToast");
resultsToast.setParams({
"title": "Deleted",
"message": "The record was deleted."
});
resultsToast.fire();
}
else if (deleteResult.state === "INCOMPLETE") {
console.log("用户离线,设备不支持草稿");
}
else if (deleteResult.state === "ERROR") {
console.log('问题删除记录,错误:' +
JSON.stringify(deleteResult.error));
}
else {
console.log('未知问题,状态:' + deleteResult.state +
', error: ' + JSON.stringify(deleteResult.error));
}
}));
}})
异步记录保存
假设情况下的时间!因此,您使用的是Salesforce应用程序,由于连接问题,保存尝试无法到达服务器。也许你所乘坐的火车进入了一个隧道,你不小心在建筑物的那个角落里漫不经心地走过,或者那个小房间再次和细胞塔混乱了。无论如何,别担心,LDS会回来的。在发生连接问题时,Lightning Data Service会将您的更改存储在本地缓存中。这由SaveRecordResult对象中的DRAFT状态指示。记录的DRAFT状态在连接恢复时解决。通过LDS保存记录时,本地缓存不会更新,直到保存完成。在服务器上成功完成保存时,缓存将更新为服务器中记录的最新版本,并通知所有引用该记录的组件。保存后,您不必担心手动将记录重新加载到缓存中。 LDS为您处理所有的工作。
- 客户端无法访问服务器。
- 组织已启用脱机草稿。
- 您拥有9.0或更高版本的Salesforce应用程序。
所有CRUD操作都尝试立即使用XMLHttpRequest解析到服务器。如果您的设备失去与服务器的连接,则Lightning Data Service可以从本地缓存中获取数据。 LDS是否从本地缓存或服务器提取数据取决于记录的年份,或者是否存在本地草案。如果记录足够新,或者存在本地草稿,则LDS将使用本地缓存。 LDS仅在需要时刷新记录,这意味着所有刷新都由组件触发。
创建一个Trailhead游乐场
好消息!您可以在免费的Trailhead Playground(TP)组织中练习使用LDS。什么是TP?这是一个为您定制的Salesforce开发版组织,可用于Trailhead。您可以启动一个TP,或创建一个新的TP,从任何动手挑战。现在就创建一个新的TP(使用现有的组织可能在检查挑战时产生问题)。滚动到此页面的底部。单击“启动”旁边的向下箭头,然后选择创建Trailhead Playground(需要登录)。如果您需要新TP的登录凭据,请按照本文中的说明进行操作。