Lightning Data Serviceで取得したレコードをApexに渡す

Lightning Data Serviceの登場により,Id以外の項目の取得が容易になりました.CRUDが容易に実現できることはもちろんですが,Lightning Data Serviceで取得したレコードをそのままApexに渡せば不要なクエリを削減できて便利です.ここで注意が必要なのは,initイベントではtargetRecordはnullとなるため,targetRecordのchangeイベントを利用しなくてはいけない点です.これはLightning Data Serviceが非同期でレコード情報を取得しているためです.最初にinitイベントで渡してしまいうまく動かなくてハマってしまいました.

簡易な例として、取引先責任者レコードをLightning Data Serviceで取得し、それをApexに渡し(わざわざSOQLで)取引先を取得してみます.

<aura:component controller="MyController" implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <aura:attribute name="contact" type="Object" />
    <aura:attribute name="account" type="Account" />
    <force:recordData recordId="{!v.recordId}" targetRecord="{!v.contact}" layoutType="FULL"/>
    <aura:handler name="init" value="{!this}" action="{!c.init}" />
    <ui:outputText value="{!v.account.Name}" />
</aura:component>
  • クライアントサイドコントローラ
({
	onInit : function(component, event, helper) {
        var action = component.get("c.getAccount");
        action.setParams({ AccountId : component.get("v.contact.AccountId") });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if(state === "SUCCESS"){
                console.log('success');
                component.set("v.account",response.getReturnValue());
            } else {
                console.log(response.getError());
            }
        });
        $A.enqueueAction(action);   
	},
})
  • Apexコントローラ
public class AccountController {
    @AuraEnabled
    public static String getAccount(Id AccountId) {
        List<Account> result = [SELECT Name From Account Where Id = :AccountId];
        if(result.size() > 0){
            return result[0];
        } else {
            return null;
        }
    }
}

onInitが呼び出される時点では,{!v.contact}はnullであるため,取引先を取得することはできません.initイベントではなく,

<aura handler="change" value="{!v.contact}" ... />

とすると,取引先責任者のレコードがロードされたタイミングで,すなわち,{!v.contact}にレコード情報が含まれた状態でクライアントサイドコントローラのメソッドを呼び出せます.