Lightning Component汎用化シリーズ（CallApex）

#1.aura:methodにより、コンポネット汎用化について
![image.png](https://qiita-image-store.s3.amazonaws.com/0/332907/789de441-ddfb-cbc5-410a-24f87fd6cffe.png)
#2.Apexのエラーハンドリングについて
![image.png](https://qiita-image-store.s3.amazonaws.com/0/332907/825aecc5-e6f9-9cb5-ae5f-eae5a0cb1c60.png)
#3.Spinnerの制御について
![image.png](https://qiita-image-store.s3.amazonaws.com/0/332907/b587bf40-7d6e-1001-c30b-647f0c93c136.png)
#4.サービスコンポネット実装
```html:fw_CallApexService.cmp
<aura:component>
	<aura:method name="callApex" action="{!c.onCallApex}">
		<aura:attribute name="callerComponent" type="Aura.Component" />
		<aura:attribute name="actionMethod" type="String" />
		<aura:attribute name="actionParameter" type="Object" />
		<aura:attribute name="callback" type="function" />
	</aura:method>
    
    <aura:attribute name="isShowSpinnerFlg" type="boolean" default="false"/>
	<aura:if isTrue="{!v.isShowSpinnerFlg}">
    	<lightning:spinner variant="brand" size="large"/>
    </aura:if>
</aura:component>
```
```javascript:fw_CallApexServiceController.js
({
	onCallApex : function(component, event, helper) {
        component.set("v.isShowSpinnerFlg", true);
		
		let params = event.getParams().arguments;
		
		let callerComponent = params.callerComponent;
		let actionMethod = params.actionMethod;
		let actionParameter = params.actionParameter;
		let callback = params.callback;
		
		let action = callerComponent.get(actionMethod);
		action.setParams(actionParameter);
		action.setCallback(this, function(response) {
			// レスポンス用のオブジェクトを取得
			let returnValue = response.getReturnValue();
			if (response.getState() === "SUCCESS") {
				// サーバ側から受信した
				callback(returnValue);
			} else if (response.getState() === "ERROR") {
				let errors = response.getError();
				if (errors && Array.isArray(errors) && errors.length > 0) {
					// サーバーサイドでcatchできなかったパターン
					helper.defaultErrorHandler(errors);
				}
			} else {
				// Handle other reponse states
				// 例：state === "INCOMPLETE"
			}
			
	        component.set("v.isShowSpinnerFlg", false);
		});
		
		$A.enqueueAction(action);
	}
})
```
```javascript:fw_CallApexServiceHelper.js
({
	defaultErrorHandler : function(errors) {
		let toastParams = {
			title: "error",
			message: "Unknown error",
			type: "error",
			mode: "sticky"
		};
		
		if (errors && Array.isArray(errors) && errors.length > 0) {
			console.error(JSON.stringify(errors));
			toastParams.message = errors[0].message;
		}
		
		let toastEvent = $A.get("e.force:showToast");
		toastEvent.setParams(toastParams);
		toastEvent.fire();
	},
})
```
#5.使用例
```java:DataServiceController.cls
public with sharing class DataServiceController {
	@AuraEnabled
	public static ReturnValue getContacts(String filter) {
		ReturnValue returnValue = new ReturnValue();
		try{
			List<Contact> contactList;
			if(String.isEmpty(filter)) {
				contactList = [SELECT Id, Name, Email FROM Contact LIMIT 10];
			} else {
				String filterString = '%' + filter + '%';
				contactList = [SELECT Id, Name, Email FROM Contact WHERE Name LIKE :filterString LIMIT 10];
			}
			// 正常終了
			returnValue.isSuccess = true;
			returnValue.contactList = contactList;
		} catch(Exception e){
			// 異常終了
			returnValue.isSuccess = false;
			returnValue.message = 'システムエラーが発生しました。' + e.getMessage();
		}
		return returnValue;
	}
	
	public class ReturnValue {
		@AuraEnabled
		public Boolean isSuccess { get; set; }
		
		@AuraEnabled
		public String message { get; set; }
		
		@AuraEnabled
		public List<Contact> contactList { get; set; }
	}
	
}
```
```html:CustomPagination.cmp
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes" controller="DataServiceController">
	<!-- サービスコンポネット -->
	<c:fw_CallApexService aura:id="callApexService"/>
	
	<!-- 受信イベント -->
	<aura:handler name="init" action="{!c.doInit}" value="{!this}"/>
	
	<!-- attribute -->
	<aura:attribute name="data" type="Object"/>
	<aura:attribute name="columns" type="List"/>
	
	<aura:attribute name="allData" type="List"/>
	<aura:attribute name="currentPageNumber" type="Integer" default="1"/>
	<aura:attribute name="pageSize" type="Integer" default="5"/>
	<aura:attribute name="totalPages" type="Integer" default="false"/>
	
	<!-- ～～省略～～ -->
</aura:component>
```
```javascript:CustomPaginationHelper.js
({
	getAllData : function(component, helper) {
		let callApexService = component.find("callApexService");
		callApexService.callApex(
			component,
			"c.getContacts",
			{"filter": ""},
			function(returnValue){
				if (returnValue.isSuccess) {
					component.set("v.allData", returnValue.contactList);
					component.set("v.totalPages", Math.ceil(component.get("v.allData").length / component.get("v.pageSize")));
					component.set("v.currentPageNumber", 1);
					helper.buildData(component, helper);
				} else {
					console.log('サーバ側にシステムエラーを発生しました。: ' + returnValue.message);
				}
			}
		);
	},

	// ～～省略～～
})
```
#6.参照資料
**・Lightning ComponentにおけるApexCallsの汎用化**
　　 https://qiita.com/isanuki/items/51f76c578f8a39bc53e5
**・LightningComponent開発におけるApexのエラーハンドリング方法**
　　 https://www.terrasky.co.jp/blog/2015/151202_001522.php