LightningのAuraで検索テーブルを作成

###・要件
Lightningでテーブルリストでのソートと検索を実現する
SalesforceのAuraでコンポーネント作成手順をまとめる



###・対応案
・Aura技術要領を把握する
・データ渡す方法を理解する

###・方法
####①DeveloperConsoleでコンポーネントを作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/50255646-4383-63fb-4bed-5e7db6d787d2.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/1020e80a-1cd0-e499-6908-b753d0c1bbd6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/1bd48735-5d56-cf6d-5a8c-f4673f2ac8d0.png)
コンポーネントに７ファイルを生成されるが、上３つだけはよく使われている

#####AccountList.cmp　→画面描写XML

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/4e667833-60d8-d955-e168-53d1108688d0.png)

```
<aura:component controller="AccountListController"
                implements="flexipage:availableForAllPageTypes,lightning:actionOverride,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:appHostable" >
    
    <aura:attribute name="acctList" type="List"/>
    <aura:attribute name="filteredData" type="List" />
    <!-- Server検索項目 -->
    <aura:attribute name="schStr" type="String" />
      
    <!-- filter input -->
    <aura:attribute name="filter" type="String" />
    <!-- Header -->
    <aura:attribute name="mycolumns" type="List"/>
     <!-- Sort -->
    <aura:attribute name="sortedBy" type="String" default="Industry"/>
    <aura:attribute name="sortedDirection" type="String" default="asc"/>
    
    <aura:handler name="init" value="{!this}" action="{!c.fetchAccounts}"/>
  
    
    <div class="demo-only" style="height: 24rem;">
    <div class="demo-only demo-only--sizing slds-grid ">
      <div class= "slds-size--1-of-8" ><span> </span> </div>
      <div class= "slds-size--2-of-8" >
        <span onkeypress="{!c.search}">
            <lightning:input type="text"  placeholder="全データからEnterキーで再検索する" 
                             value="{!v.schStr}"  />
        </span></div>
     
     <div class= "slds-size--3-of-8" ><span></span></div>
    <div class= "slds-size--１-of-8" >
    		<span>
        	<lightning:input type="text"  placeholder="結果からフィルタする" onchange="{!c.filter}" value="{!v.filter}"  />
         </span>
 	 </div>
     <div class= "slds-size--1-of-8" ><span></span></div>
     </div>	  
    	<lightning:datatable data="{!v.filteredData}" 
                         columns="{!v.mycolumns}" 
                         keyField="id"
                         hideCheckboxColumn="false"
                         onsort="{!c.updateColumnSorting}"
                         sortedBy="{!v.sortedBy}"  
                         sortedDirection="{!v.sortedDirection}"/>
      
     </div> 
</aura:component>
```
#####AccountListController.js　→画面描写JS
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/81a92c2f-2ce4-4dd6-87c4-c1dc5eed930d.png)

```
({
    fetchAccounts : function(component, event, helper) {
        component.set('v.mycolumns', [
             {label: 'Account Name', fieldName: 'linkName', type: 'url', 
              typeAttributes: {label: { fieldName: 'Name' }}, sortable: true},
            {label: 'Industry', fieldName: 'Industry', type: 'text', sortable: true},
            {label: 'Type', fieldName: 'Type', type: 'text', sortable: true},
            {label: 'Number Of Employees', fieldName: 'NumberOfEmployees', 
                    type: 'number',cellAttributes: { alignment: 'left' }, sortable: true},
            {label: 'Clean Status', fieldName: 'CleanStatus', type: 'text', sortable: true},
        ]);
        var action = component.get("c.fetchAccts");
        var schStr = component.get("v.schStr");
        if (schStr== null ||schStr== undefined){
            schStr='';
        }
        schStr = '%' + schStr + '%';
            action.setParams({ keyWord : schStr});
        action.setCallback(this, function(response){
            var state = response.getState();
            if (state === "SUCCESS") {
                // Link
                var records = response.getReturnValue();
                records.forEach(function(record){
                    record.linkName = '/'+record.Id;
                });
                component.set("v.acctList", records);
                //sort
                component.set("v.filteredData",records);
                helper.sortData(component, component.get("v.sortedBy"), component.get("v.sortedDirection"));
            }
        });
        $A.enqueueAction(action);
    },
    updateColumnSorting: function (cmp, event, helper) {
        var fieldName = event.getParam('fieldName');
        var sortDirection = event.getParam('sortDirection');
        cmp.set("v.sortedBy", fieldName);
        cmp.set("v.sortedDirection", sortDirection);
        helper.sortData(cmp, fieldName, sortDirection);
    },
    filter: function(component, event, helper) {
        var data = component.get("v.acctList"),
            term = component.get("v.filter"),
            results = data, regex;
        try {
            regex = new RegExp(term, "i");
            // filter checks each row, constructs new array where function returns true
              results = data.filter(row=>regex.test(row.Name)
                                  || regex.test(row.Industry)
                                  || regex.test(row.Type)
            || regex.test(row.NumberOfEmployees==undefined?"":row.NumberOfEmployees.toString())
                                  || regex.test(row.CleanStatus)
                               );
        } catch(e) {
            // invalid regex, use full list
            alert(e);
        }
        component.set("v.filteredData", results);
    },
    search: function(component, event, helper){
            //alert("msg " + event.which);
            if(event.which == 13) { 
       var action = component.get("c.fetchAccts");
        var schStr = component.get("v.schStr");
        if (schStr== null ||schStr== undefined){
            schStr='';
        }
       schStr = '%' + schStr + '%';
            action.setParams({ keyWord : schStr});
           // alert(schStr);
        action.setCallback(this, function(response){
            var state = response.getState();
           // alert(state);
            if (state === "SUCCESS") {
                // Link
               
                var records = response.getReturnValue();
            // alert(records);
                records.forEach(function(record){
                    record.linkName = '/'+record.Id;
                });
                component.set("v.acctList", records);
                //sort
                component.set("v.filteredData",records);
               helper.sortData(component, component.get("v.sortedBy"), component.get("v.sortedDirection"));
            }
        });
        $A.enqueueAction(action);

            }
    }
})
```

#####AccountListHelper.js　→画面データ処理の共通JS
```
({
    sortData: function (cmp, fieldName, sortDirection) {
        var data = cmp.get("v.filteredData");
        var reverse = sortDirection !== 'asc';
        data.sort(this.sortBy(fieldName, reverse))
        cmp.set("v.filteredData", data);
    },
    sortBy: function (field, reverse, primer) {
        var key = primer ?
            function(x) {return primer(x[field])} :
            function(x) {return x[field]};
        reverse = !reverse ? 1 : -1;
        return function (a, b) {
            return a = key(a)?key(a):'', b = key(b)?key(b):'', reverse * ((a > b) - (b > a));
        }
    }
})
```
####②テスト方法
Appページを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/e1154c3a-09e2-7c23-323d-ceb2afcc4d25.png)

testAccoutList.app　Previewボタンを押す

```
<aura:application extends="force:slds" >
            <c:AccountList/>
</aura:application>

```

####③画面へ配置
例Opportunitye画面を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/ab0096d5-1f45-058f-e49a-99946ffa01a6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/f3b32d78-8f5b-e2e6-5cc4-a10c31aef025.png)

####④画面のSFIDを渡す方法
画面レコードSFIDはXMLに使える
<aura:attribute name="recordId" type="Id" />

####⑤Apexの実装
AccountListController.apex
```
public with sharing class AccountListController {

    @AuraEnabled
    public static List < Account > fetchAccts( String keyWord) {
       
        return [ SELECT Id, Name, Industry, Type,NumberOfEmployees,CleanStatus FROM Account 
                 where Name like :keyWord
                    OR Industry like :keyWord
                    OR Type like :keyWord
                   // OR NumberOfEmployees like :keyWord
                    OR CleanStatus like :keyWord
                
                Limit 100 ];
       
    /*    
        List<List<SObject>> customerAccountSearchList = new List<List<SObject>>();
        customerAccountSearchList = [FIND :keyWord IN ALL  Fields 
         RETURNING Account(Id, Name, Industry, Type,NumberOfEmployees,CleanStatus)];
        Account [] searchedAccount = ((List<Account>)customerAccountSearchList[1]);
        return searchedAccount;   */
    }
    
}
```