取引先に関連する取引先責任者を一覧で表示して、一括更新するAura コンポーネント

Answersの質問で上記のサンプルを紹介しているサイトを教えて欲しいとありました。探したのですがいいのがないです。仕方ない。サクッと作ってみましょう。
https://trailblazers.salesforce.com/answers?id=9064S000000kHFzQAM

こんなイメージ（赤い四角のところ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/6f7f0135-dc02-abcf-3eae-16b6ffaf1b87.png)


コンポーネント

```
<aura:component controller="AccountContacts" implements="flexipage:availableForAllPageTypes,force:hasRecordId" access="global">
	<!-- ***************************************************************** -->
    <!-- AccountContacts                                                   -->
    <!-- https://trailblazers.salesforce.com/answers?id=9064S000000kHFzQAM -->
    <!--  K.Otsubo 2021/05/30                                              -->
    <!--                                                                   -->
    <!-- ***************************************************************** -->
    
    <aura:attribute name="recordId" type="String" /> 
    <aura:attribute name="message" type="String" />
    <aura:attribute name="myData" type="List" />
    <aura:attribute name="myColumns" type="List" />
    <aura:attribute name="showSaveCancelBtn" type="boolean" default="false"/>
    
    <aura:attribute name="sortedBy" type="String" />
    <aura:attribute name="sortedDirection" type="String" />
    <aura:attribute name="draftValues" type="List" />
    <aura:attribute name="contactList" type="List" default=""/>
    
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    
    <div class="slds-box slds-box_xx-small slds-text-align_left slds-m-around_xx-small slds-theme_default">
        <lightning:layout verticalAlign="left" multipleRows="true">
			<div class="slds-size_12-of-12">
                <div class="slds-m-around_xx-small">
                    {!v.message}
                </div>
            </div>
            
            <div class="slds-size_12-of-12">
                <aura:if isTrue="{!v.showSaveCancelBtn}">
                    <div class="slds-xx-small-buttons--horizontal">
                        <div class="slds-m-around_xx-small">
                            <lightning:button label="Cancel" onclick="{!c.Cancel}" />
                            <lightning:button label="Save" onclick="{!c.Save}" variant="brand" />
                        </div>
                    </div>   
                </aura:if>
            </div>
            
            <div class="slds-size_12-of-12">
                <div class="slds-scrollable" style="height:100%;">
                    <lightning:datatable data="{!v.myData}" columns="{!v.myColumns}" 
                                         aura:id="myDataTable"
                                         onsort="{!c.updateColumnSorting}"
                                         sortedDirection="{!v.sortedDirection}" 
                                         onrowselection="{! c.getSelectedName }"
                                         onrowaction="{!c.handleRowAction}"
                                         hideCheckboxColumn ="false"
                                         minColumnWidth="40"
                                         selectedRows="{!v.draftValues}"
                                         sortedBy="{!v.sortedBy}" keyField="Id" />
                </div>
            </div>
            
            {!v.contactList}
        </lightning:layout>
    </div>
    
    
</aura:component>
```

コントローラ

```
({
	doInit : function(component, event, helper) {            
        component.set("v.message","");
        helper.getRecordALL(component, event);    
         
	},
    
    getSelectedName: function (component, event, helper) {
        var selectedRows = event.getParam('selectedRows');       
        var selectedRows_length  = selectedRows.length ;
        
        component.set("v.showSaveCancelBtn","True");
        
        var chkMap = component.get("v.chkMap");
        var chkMapNew ={};
        //for (var i = 0,len=selectedRows_length ; i < len; i++){
        //    chkCount0 = chkMap[selectedRows[i].Id];           
        //}
        component.set("v.contactList",selectedRows);

    },
    
    Save: function (component, event, helper) {
        var contactList = component.get("v.contactList");
        alert(JSON.stringify(contactList));
        //Please write the logic at the time of saving here
    },
    
    Cancel: function (component, event, helper) {
        component.set("v.contactList","");
        component.set("v.draftValues","");
        component.set("v.showSaveCancelBtn","False");
    },
    
    
})
```


ヘルパー

```
({
	getRecordALL : function(component, event) {
        var recordId = component.get("v.recordId");
		var action = component.get("c.getInitSearch");
        action.setParams({"recordId":recordId});
        action.setCallback(this, function(response){
            if (action.getState() == "SUCCESS") {            	
                var myVal = response.getReturnValue();
                component.set("v.myColumns",myVal.myColumns);
        		component.set("v.myData",myVal.myData);

            }  else if (action.getState() == "ERROR" ) {
                var errors = response.getError();
                if (errors[0] && errors[0].message) {
                	component.set("v.message", errors[0].message);
                } 
            }
        });
        $A.enqueueAction(action);
	},
})
```


Apex class

```
public with sharing class AccountContacts {
	// *******************************************************************
    // AccountContacts 
    // https://trailblazers.salesforce.com/answers?id=9064S000000kHFzQAM               
    // K.Otsubo 2021/05/30    
    //                 
    // *******************************************************************

	    @AuraEnabled
    public static Map<String,Object> getInitSearch(String recordId) {
        Map<String,Object>  RetMap = new Map<String,Object>();
        system.debug(Logginglevel.INFO,'### logging ############ ----> '+ recordId );     
        RetMap.put('myColumns',getColumns ());
        RetMap.put('myData',getData (recordId));
        
        return RetMap;
    }
    
    public static List<Map<String,Object>> getData (String recordId) {    
        List<Map<String,Object>> myDataList = new List<Map<String,Object>>();
        if (String.isEmpty(recordId)) return myDataList;
        if (recordId == 'undefined') return myDataList;
        
        String mySOQL = 'SELECT Id,FirstName,LastName,email, ' + 
            			' CreatedBy.Name,CreatedDate,LastModifiedBy.Name,LastModifiedDate ' +
                        ' FROM Contact ' +
                        ' WHERE LastModifiedDate != null AND AccountId=\'' + recordId + '\' ' + 
                        ' ORDER BY FirstName,LastName LIMIT 200';
        
        system.debug(Logginglevel.INFO,'### logging ############ ----> '+ mySOQL );     
        List<Contact> myContactList = Database.query(mySOQL);
        
        for (Contact myCon : myContactList) {
            Map<String, Object> myMap = new Map<String, Object>();        	
        	myMap.put('Id',myCon.Id);            
            myMap.put('FirstName',myCon.FirstName);
            String Name_st = '/lightning/r/Contact/' + myCon.Id  +'/view';
            myMap.put('Name_st',Name_st);
            myMap.put('urlLabel',myCon.FirstName);
            myMap.put('LastName',myCon.LastName);      
            myMap.put('email',myCon.email);           
            myDataList.add(myMap);
        }
        
        return myDataList;
    }
    
    public static List<Map<String,Object>> getColumns () {    
        List<Map<String,Object>> myTabList = new List<Map<String,Object>>();
        
        myTabList.add(mapColumn('url','FirstName','Name_st',true,180,false));
        myTabList.add(mapColumn('text','LastName','LastName',true,180,false));
        myTabList.add(mapColumn('text','email','email',false,180,false));
            
        return myTabList;
    }
    
    
    public static Map<String,Object> mapColumn (String myType,
                                                String myLabel,
                                                String myFieldName,
                                                Boolean mySortable,
                                                Integer myInitialWidth,
                                                Boolean myEditable) {
       Map<String,Object> myMap = new Map<String,Object>();
                                                    
        switch on myType {           
        	when 'url' {
				myMap.put('label',myLabel);        
                myMap.put('fieldName',myFieldName.trim());        
                myMap.put('type',myType);
                if (mySortable == true ) myMap.put('sortable','true');
                if (myEditable == true ) myMap.put('editable','true'); 
                myMap.put('editable',myEditable); 
                myMap.put('initialWidth',myInitialWidth); 
                Map<String,String> actions2 = new  Map<String,String>();
                actions2.put('fieldName','urlLabel');                
                Map<String,Object> actions = new  Map<String,Object>();
                actions.put('label',actions2);               
                actions.put('tooltip',actions2);
                actions.put('target','_self'); 
                myMap.put('typeAttributes',actions);
            }
           
            when 'boolean' {
                myMap.put('type',myType);
                myMap.put('label',myLabel);
                myMap.put('fieldName',myFieldName.trim());                
                if (mySortable == true ) myMap.put('sortable','true');
                if (myEditable == true ) myMap.put('editable','true'); 
                myMap.put('initialWidth',myInitialWidth);
                
            }
            when 'text' {
                myMap.put('type',myType);
                myMap.put('label',myLabel);
                myMap.put('fieldName',myFieldName.trim());        
                if (mySortable == true ) myMap.put('sortable','true');
                if (myEditable == true ) myMap.put('editable','true'); 
                myMap.put('wrapText','true');
                myMap.put('initialWidth',myInitialWidth); 
            }
            when 'date2' {
                myMap.put('type','date');
                myMap.put('label',myLabel);
                myMap.put('fieldName',myFieldName.trim());        
                if (mySortable == true ) myMap.put('sortable','true');
                if (myEditable == true ) myMap.put('editable','true'); 
                myMap.put('initialWidth',myInitialWidth);
                Map<String,Object> myAttributes = new  Map<String,Object>();                
                myAttributes.put('year','2-digit');
                myAttributes.put('month','2-digit');
                myAttributes.put('day','2-digit');
                myMap.put('typeAttributes',myAttributes);
            }
           
            when else {
                myMap.put('type',myType);
                myMap.put('label',myLabel);
                myMap.put('fieldName',myFieldName.trim());        
                if (mySortable == true ) myMap.put('sortable','true');
                if (myEditable == true ) myMap.put('editable','true'); 
                myMap.put('initialWidth',myInitialWidth);
            }
        }
        return myMap;
    }

}
```
社内で使っている便利クラスを使わないように変更するのに手間取りました。都合70分でしょうか。
もっと早くできると思ったんですがね。