Lightning-数据服务(3)

学习目标

完成本单元后,您将能够:

  • 解释Lightning Data Service如何使用通知。
  • 使用recordUpdated来处理错误并记录更改。

记录更改

在最后一个单元中,我们介绍了Lightning Data Service如何处理CRUD。现在让我们来看看如何在记录更改时采取措施,以便您的组件可以响应记录加载,更改,更新或删除操作。

要在记录更改时采取措施,请处理recordUpdated事件。

<force:recordData aura:id="forceRecordDataCmp"
    recordId="{!v.recordId}" 
    layoutType="{!v.layout}"
    targetRecord="{!v.record}"
    targetFields="{!v.simpleRecord}"
    targetError="{!v.error}"
    recordUpdated="{!c.recordUpdated}" />
实现处理更改的动作处理程序。字段更改通过changedFields对象传入,该对象包含与新值关联的旧字段值。
({
    recordUpdated: function(component, event, helper) {
        var eventParams = event.getParams();
        if(eventParams.changeType === "CHANGED") {
            // 获取为此记录更改的字段
            var changedFields = eventParams.changedFields;
            console.log('Fields that are changed: ' + JSON.stringify(changedFields));
            // 记录被改变,所以刷新组件(或其他组件逻辑)
            var resultsToast = $A.get("e.force:showToast");
            resultsToast.setParams({
                "title": "Saved",
                "message": "The record was updated."
            });
            resultsToast.fire();
        } else if(eventParams.changeType === "LOADED") {
            console.log("Record is loaded successfully.");
        } else if(eventParams.changeType === "REMOVED") {
            var resultsToast = $A.get("e.force:showToast");
            resultsToast.setParams({
                "title": "Deleted",
                "message": "The record was deleted."
            });
            resultsToast.fire();
        } else if(eventParams.changeType === "ERROR") {
            console.log('Error: ' + component.get("v.error"));
        }
    }
})
当LDS检测到记录更改时,会通知使用更改记录的组件。如果您不处理更改,记录仍会更新,因此对targetRecord或targetFields属性的任何引用都会自动显示在您的组件中。对于每个强制:recordData组件引用更新的记录,LDS做两件事情。
  • LDS通过使用适当的changeType和changedFields值触发recordUpdated事件来通知所有其他的force的实例:recordData。
  • 它将每个force:recordData上的targetRecord和targetFields属性设置为新的记录值。如果targetRecord或targetFields被任何UI引用,则会自动触发重新渲染,以便UI显示最新的数据。

注意

如果force:recordData处于EDIT模式,则当记录更改时,targetRecord和targetFields不会自动更新。这是为了避免仍在进行的clobberin编辑,并防止未保存的更改出现在其他组件中。不用担心,可以通过处理recordUpdated事件并调用reloadRecord方法手动刷新记录。

当LDS检测到源自服务器的更改时,它使用相同的更改通知机制。 LDS在收到记录的新请求时检测到服务器上的更改。 LDS仅通知已注册并标记为isValid的组件。处理recordUpdated事件时,请检查changeType以确定要处理的更改类型。

错误处理

如果加载时发生错误,则将targetError属性设置为本地化的错误消息。如果强制属性:recordData无效,或者服务器不可访问且记录不在本地缓存中,则会发生错误。从那里,你决定如何显示错误。

如果记录在服务器上无法访问,那么recordUpdated事件触发changeType = REMOVED,并且没有错误设置为targetError,因为记录变得不可访问有时是预期的结果。由于记录或实体共享和可见性设置,或记录被删除,记录也可能变得不可访问。

把它放在一起

恭喜!现在您已经知道开始使用Lightning Data Service所需了解的一切。这是相对简单的,但它做了很多!在你脱颖而出并获得那个新奇的徽章之前,让我们把所有这些理论付诸实践。我们将放置一个页面,其中包含两个使用相同记录数据的组件,并正确响应记录更改。

该组件显示联系人的详细信息。请注意,它使用字段而不是layoutType,targetFields而不是targetRecord。请记住,可以包含fields或layoutType(或两者!),并且可以使用targetFields或targetRecord(或两者!)来检索记录数据。对于字段,您必须指定要查询的特定字段,而使用layoutType时,只需指定要使用的记录布局,即FULL或COMPACT。如果使用targetFields检索首选方法的数据,请在UI中使用v.targetFields.Name格式。如果您使用targetRecord,请使用v.targetRecord.fields.Name.value。

ldsShowContact.cmp

<aura:component implements="force:hasRecordId,flexipage:availableForRecordHome">

    <aura:attribute name="contactRecord" type="Object"/>
    <aura:attribute name="recordLoadError" type="String"/>
    
    <force:recordData aura:id="recordLoader"
        recordId="{!v.recordId}"
        fields="Name,Description,Phone,Industry"
        targetFields="{!v.contactRecord}"
        targetError="{!v.recordLoadError}"
    />

    <!-- 显示有关联系人详情的闪电卡 -->
    <div class="Contact Details"> 
        <lightning:card iconName="standard:contact" title="{!v.contactRecord.Name}" >
            <div class="slds-p-horizontal--small">
                <p class="slds-text-heading--small">
                    <lightning:formattedPhone title="Phone"  value="{!v.contactRecord.Phone}" /></p>
                <p class="slds-text-heading--small">
                    <lightning:formattedText title="Description" value="{!v.contactRecord.Description}" /></p>
                <p class="slds-text-heading--small">
                     <lightning:formattedText title="Industry" value="{!v.contactRecord.Industry}" /></p>
            </div>
        </lightning:card>
    </div>

</aura:component>
我们的下一个组件加载相同的联系人,但在编辑模式下,还有一个让用户编辑联系人的表单。它还处理recordUpdated事件,以便我们可以根据编辑的结果采取某些操作。
ldsEditContact.cmp

<aura:component implements="force:hasRecordId,flexipage:availableForRecordHome">

    <aura:attribute name="contactRecord" type="Object"/>
    <aura:attribute name="recordSaveError" type="String" default=""/>

    <!-- Load record in EDIT mode -->
    <force:recordData aura:id="recordLoader"
        recordId="{!v.recordId}"
        fields="Name,Description,Phone,Industry"
        targetFields="{!v.contactRecord}"
        targetError="{!v.recordSaveError}"
        mode="EDIT" 
        recordUpdated="{!c.handleRecordUpdated}" />

    <!-- Contact edit form -->
    <div class="Edit Contact">
        <lightning:card iconName="action:edit" title="Edit Contact">
            <div class="slds-p-horizontal--small">
                <lightning:input label="Contact Name" value="{!v.contactRecord.Name}"/>
                <lightning:input label="Contact Description" value="{!v.contactRecord.Description}"/>
                <lightning:input label="Contact Phone" value="{!v.contactRecord.Phone}"/>
                <br/>
                <lightning:button label="Save Contact" variant="brand" onclick="{!c.saveContact}" />
            </div>
        </lightning:card>
    </div>
    
    <!-- Display error message -->
    <aura:if isTrue="{!not(empty(v.recordSaveError))}">
        <div class="recordSaveError">
            {!v.recordSaveError}</div>
    </aura:if>

</aura:component>
最后,我们有我们的控制器,根据编辑的结果,我们的控制器会报告一个成功的编辑信息或向我们显示错误信息。
ldsEditContactController.js

({
    saveContact : function(cmp, event, helper) {
        var recordLoader = cmp.find("recordLoader");
        recordLoader.saveRecord($A.getCallback(function(saveResult) {
            if (saveResult.state === "ERROR") {
                var errMsg = "";
                // saveResult.error是一个错误数组,
                // 将所有错误收集到一个消息中
                for (var i = 0; i < saveResult.error.length; i++) {
                    errMsg += saveResult.error[i].message + "\n";
                }
                cmp.set("v.recordSaveError", errMsg);
            } else {
                cmp.set("v.recordSaveError", "");
            }
        }));
    },

    // 在更改记录时(通过任何组件),在这里控制组件行为
    handleRecordUpdated: function(component, event, helper) {
        var eventParams = event.getParams();
        if(eventParams.changeType === "CHANGED") {
            // 获取为此记录更改的字段
            var changedFields = eventParams.changedFields;
            console.log('Fields that are changed: ' + JSON.stringify(changedFields));
            // 记录被改变,所以刷新组件(或其他组件逻辑)
            var resultsToast = $A.get("e.force:showToast");
            resultsToast.setParams({
                "title": "Saved",
                "message": "The record was updated."
            });
            resultsToast.fire();
        } else if(eventParams.changeType === "LOADED") {
            // record is loaded in the cache
        } else if(eventParams.changeType === "REMOVED") {
            // record is deleted and removed from the cache
        } else if(eventParams.changeType === "ERROR") {
            console.log('Error: ' + component.get("v.error"));
        }
    }
})
你有它,你是一个闪电数据服务的主人。 现在出发,使用新发现的技能来改善各地开拓者的闪电组件的性能和一致性。