今回はlightning:datatableを用いた関連リストにCSVエクスポートボタンを追加し、CSV出力機能を追加しました。
また、本記事記載のソールコードにはCSV出力機能の他に以下の機能が盛り込まれています。
- 新規取引先レコード作成
- 取引先レコード編集(行アクション)
- 取引先レコード削除(行アクション)
- 新規取引先レコード作成権限チェック
- 取引先削除権限チェック
- ページネーション
<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" controller="ContactListController01">
<aura:attribute name="title" type="String"/>
<aura:attribute name="data" type="Object"/>
<aura:attribute name="columns" type="List"/>
<aura:attribute name="recId" type="String"/>
<aura:attribute name="labelMap" type="Map" default="{}"/>
<aura:attribute name="rowNumber" type="Integer" default="0"/>
<aura:attribute name="pageSize" type="Integer" default="10"/>
<aura:attribute name="currentPageNumber" type="Integer" default="1"/>
<aura:attribute name="totalPages" type="Integer" default="0"/>
<aura:attribute name="showNewButton" type="Boolean" default="false"/>
<aura:attribute name="showDatatable" type="Boolean" default="false"/>
<aura:attribute name="showConfirmDialog" type="Boolean" default="false"/>
<aura:handler name="init" action="{!c.init}" value="{!this}"/>
<!--Contact List-->
<article class="slds-card slds-theme_shade">
<div class="slds-card__header slds-grid">
<header class="slds-media slds-media_center slds-has-flexi-truncate">
<div class="slds-media__figure">
<span class="slds-icon_container slds=icon-standard-contact" title="contact">
<lightning:icon iconName="standard:contact" alternativeText="Contact" title="Contact" size="small"/>
</span>
<span class="slds-assistive-text">contact</span>
</div>
<div class="slds-media__body">
<h2 class="slds-card__header-title cardTitle">
<span class="slds-card__header-link slds-truncate" style="margin-top:4px;">{!v.title}</span>
</h2>
</div>
<aura:if isTrue="{!v.showNewButton}">
<lightning:button label="New" onclick="{!c.handleNew}"/>
</aura:if>
<aura:if isTrue="{!v.showDatatable}">
<lightning:button label="CSV" onclick="{!c.handleCsv}"/>
</aura:if>
</header>
</div>
<aura:if isTrue="{!v.showDatatable}">
<div style="border: 1px solid #D8D8D8;">
<lightning:datatable aura:id="ContactList"
columns="{!v.columns}"
data="{!v.data}"
keyField="Id"
showRowNumberColumn="true"
rowNumberOffset="{!v.rowNumber}"
onrowaction="{!c.handleRowAction}"
/>
</div>
<!--Pagenatin-->
<center>
<br/>
<lightning:button class="slds-m-bottom_medium"
label="First"
iconName="utility:left"
iconPosition="left"
onclick="{! c.onFirst }"
disabled="{! v.currentPageNumber == 1 }" />
<lightning:button class="slds-m-bottom_medium"
label="Previous"
iconName="utility:chevronleft"
iconPosition="left"
onclick="{! c.onPrev }"
disabled="{! v.currentPageNumber == 1 }" />
<span class="slds-m-horizontal_x-small">
Page {! v.currentPageNumber } of {! v.totalPages}
</span>
<lightning:button class="slds-m-bottom_medium"
label="Next"
iconName="utility:chevronright"
iconPosition="right"
onclick="{! c.onNext }"
disabled="{! v.currentPageNumber == v.totalPages }" />
<lightning:button class="slds-m-bottom_medium"
label="Last"
iconName="utility:right"
iconPosition="right"
onclick="{! c.onLast }"
disabled="{! v.currentPageNumber == v.totalPages }" />
</center>
</aura:if>
</article>
<!-- Delete modal -->
<aura:if isTrue="{!v.showConfirmDialog}">
<div role="dialog" class="slds-modal slds-fade-in-open">
<div class="slds-modal__container">
<header class="slds-modal__header">
<h1 class="slds-text-heading--medium">Delete Contact</h1>
</header>
<div class="slds-modal__content slds-p-around--medium">
<center><b>Are you sure you want to delete this Contact?</b></center>
</div>
<footer class="slds-modal__footer">
<lightning:button name="No" label="Cancel" onclick="{!c.handleConfirmDialogNo}"/>
<lightning:button name="Yes" label="Delete" onclick="{!c.handleConfirmDialogYes}"/>
</footer>
</div>
</div>
<div class="slds-backdrop slds-backdrop--open"/>
</aura:if>
</aura:component>
({
/** init **/
init : function(component, event, helper) {
helper.init(component, event, helper);
},
/** CSV output **/
handleCsv : function(component, event, helper) {
let url = '/apex/ContactCsvExport?id='+component.get("v.recordId");
window.open(url, '_blank');
},
/** create new Contact **/
handleNew : function(component, event, helper) {
helper.handleNew(component, event, helper);
},
/** row action **/
handleRowAction : function(component, event, helper) {
helper.handleRowAction(component, event, helper);
},
/** delete ConfirmDialog "yes" **/
handleConfirmDialogYes : function(component, event, helper) {
helper.handleConfirmDialogYes(component, event, helper);
},
/** delete ConfirmDialog "no" **/
handleConfirmDialogNo : function(component, event, helper) {
helper.handleConfirmDialogNo(component, event, helper);
},
/** onFirst **/
onFirst : function(component, event, helper) {
component.set("v.currentPageNumber", 1);
component.set("v.rowNumber", 0);
helper.init(component, helper);
},
/** onPrev **/
onPrev : function(component, event, helper) {
component.set("v.currentPageNumber", component.get("v.currentPageNumber")-1);
component.set("v.rowNumber", component.get("v.rowNumber")-component.get("v.pageSize"));
helper.init(component, helper);
},
/** onNext **/
onNext : function(component, event, helper) {
component.set("v.currentPageNumber", component.get("v.currentPageNumber")+1);
component.set("v.rowNumber", component.get("v.rowNumber")+component.get("v.pageSize"));
helper.init(component, helper);
},
/** onLast **/
onLast : function(component, event, helper) {
component.set("v.currentPageNumber", component.get("v.totalPages"));
component.set("v.rowNumber", (component.get("v.totalPages")-1)*component.get("v.pageSize"));
helper.init(component, helper);
}
})
({
/** init **/
init : function(component, event, helper) {
// get Contact label
var getContactLabelAction = component.get("c.getContactLabel");
getContactLabelAction.setCallback(this, function(response){
var state = response.getState();
if(state === "SUCCESS"){
var result = response.getReturnValue();
// set Contact label
component.set("v.labelMap", result);
// row action
var actions = [
{label: 'Edit', name: 'edit'},
{label: 'Delete', name: 'delete'}
]
// set columns
component.set("v.columns", [
{label: component.get("v.labelMap")['Name'], fieldName: 'LinkName', type: 'url', typeAttributes: {label: {fieldName: 'Name'}, tooltip: {fieldName: 'Name'}}, initialWidth: 150},
{label: component.get("v.labelMap")['Title'], fieldName: 'Title', type: 'text', initialWidth: 150},
{label: component.get("v.labelMap")['Email'], fieldName: 'Email', type: 'email', initialWidth: 150},
{label: component.get("v.labelMap")['Phone'], fieldName: 'Phone', type: 'phone', initialWidth: 150},
{label: component.get("v.labelMap")['Department'], fieldName: 'Department', type: 'text', initialWidth: 150},
{label: component.get("v.labelMap")['Age__c'], fieldName: 'Age__c', type: 'text', initialWidth: 150},
{label: component.get("v.labelMap")['Birthdate'], fieldName: 'Birthdate', type: 'date', initialWidth: 150},
{label: component.get("v.labelMap")['IsActive__c'], fieldName: 'IsActive__c', type: 'boolean'},
{type: 'action', typeAttributes: { rowActions: actions }}
]);
}
});
$A.enqueueAction(getContactLabelAction);
// get Contact
var getContactAction = component.get("c.getContact");
// record size per page
var pageSize = component.get("v.pageSize").toString();
// current page number
var currentPageNumber = component.get("v.currentPageNumber").toString();
// set params
getContactAction.setParams({
"recordId" : component.get("v.recordId"),
"pageSize" : pageSize,
"currentPageNumber" : currentPageNumber
});
getContactAction.setCallback(this, function(response){
var state = response.getState();
if(state === "SUCCESS"){
var result = response.getReturnValue();
// set link
result.forEach(function(record){
record.LinkName = '/' + record.Id;
});
component.set("v.data", result);
}
});
$A.enqueueAction(getContactAction);
// set object name
component.set("v.title", "Contact")
// count Contact records
var countContactAction = component.get("c.countContact");
// set params
countContactAction.setParams({
"recordId" : component.get("v.recordId")
});
countContactAction.setCallback(this, function(response){
var state = response.getState();
if(state === "SUCCESS"){
var result = response.getReturnValue();
if(result > 0){
// show datatable
component.set("v.showDatatable", true);
}
// show record number next to tilte
component.set("v.title", component.get("v.title").concat(" (", result, ")"));
// set total page size
component.set("v.totalPages", Math.ceil(result/component.get("v.pageSize")));
}
});
$A.enqueueAction(countContactAction);
// permission check to create new Contact
var isCreatableAction = component.get("c.isCreatable");
isCreatableAction.setCallback(this, function(response){
var state = response.getState();
if(state === "SUCCESS"){
var result = response.getReturnValue();
// show NEW button
component.set("v.showNewButton", result);
}
});
$A.enqueueAction(isCreatableAction);
},
/** create new Contact **/
handleNew : function(component, event, helper){
var createRecord = $A.get("e.force:createRecord");
createRecord.setParams({
"entityApiName" : "Contact",
"defaultFieldValues" : {'AccountId' : component.get("v.recordId")}
})
createRecord.fire();
},
/** row action **/
handleRowAction : function(component, event, helper){
var action = event.getParam('action');
var row = event.getParam('row');
var recId = row.Id;
component.set("v.recId", recId);
switch(action.name){
case 'edit':
var editRecordEvent = $A.get("e.force:editRecord");
editRecordEvent.setParams({
"recordId" : recId
});
//call edit
editRecordEvent.fire();
break;
case 'delete':
// show delete dialog
component.set("v.showConfirmDialog", true);
break;
}
},
/** delete ConfirmDialog "yes" **/
handleConfirmDialogYes : function(component, event, helper){
// hide dailog
component.set("v.showConfirmDialog", false);
//get recordId
var recId = component.get("v.recId");
//delete Contact
var action = component.get("c.deleteContact");
// set params
action.setParams({
"recordId" : recId
});
action.setCallback(this, function(response){
var state = response.getState();
if(state === "SUCCESS"){
if(response.getReturnValue() === null){
this.showToast({
"title": "Delete",
"type": "success",
"message":"Delete Success"});
//削除した後のリロード
this.reloadDataTable();
}else{
//delete fail
this.showToast({
"title": "Error",
"type" : "error",
"message" : response.getReturnValue()
});
}
}
});
$A.enqueueAction(action);
},
/** delete ConfirmDialog "no" **/
handleConfirmDialogNo : function(component, event, helper){
// hide dailog
component.set("v.showConfirmDialog", false);
},
/** show message **/
showToast:function(params){
var toastEvent = $A.get("e.force:showToast");
if(toastEvent){
toastEvent.setParams(params);
toastEvent.fire();
} else{
alert(params.message);
}
},
/** reload **/
reloadDataTable : function(){
var refreshEvent = $A.get("e.force:refreshView");
if(refreshEvent){
refreshEvent.fire();
}
}
})
public class ContactList01Controller {
// get Contact label
@AuraEnabled
public static Map<String, String> getContactLabel(){
Map<String, String> fieldNameMap = new Map<String, String>();
fieldNameMap.put('Name', Schema.SObjectType.Contact.fields.Name.Label);
fieldNameMap.put('Title', Schema.SObjectType.Contact.fields.Title.Label);
fieldNameMap.put('Email', Schema.SObjectType.Contact.fields.Email.Label);
fieldNameMap.put('Phone', Schema.SObjectType.Contact.fields.Phone.Label);
fieldNameMap.put('Department', Schema.SObjectType.Contact.fields.Department.Label);
fieldNameMap.put('Age__c', Schema.SObjectType.Contact.fields.Age__c.Label);
fieldNameMap.put('Birthdate', Schema.SObjectType.Contact.fields.Birthdate.Label);
fieldNameMap.put('IsActive__c', Schema.SObjectType.Contact.fields.IsActive__c.Label);
system.debug(fieldNameMap);
return fieldNameMap;
}
// get Contact
@AuraEnabled
public static List<Contact> getContact(Id recordId, String pageSize, String currentPageNumber){
Integer recSize = Integer.valueOf(pageSize);
Integer curPageNumber = Integer.valueOf(currentPageNumber)-1;
return [Select Id, Name, Title, Email, Phone, Department, Age__c, Birthdate, IsActive__c From Contact
Where AccountId =: recordId
Limit: recSize OffSet: (recSize * curPageNumber)];
}
// count Contact record
@AuraEnabled
public static Integer countContact(Id recordId){
return [Select Count() From Contact Where AccountId =: recordId];
}
// permission check to create new Contact
@AuraEnabled
public static Boolean isCreatable(){
return Schema.SObjectType.Contact.isCreateable();
}
// delete Contact
@AuraEnabled
public static String deleteContact(String recordId){
try{
// permission check to delete Contact
if(Schema.SObjectType.Contact.isDeletable() == false){
return 'No permission to delete this record.';
}
List<Contact> conList = [Select Id From Contact Where Id =: recordId];
delete conList;
return null;
}catch(Exception e){
return e.getMessage();
}
}
}
<apex:page controller="ContactCsvExportController" action="{!export}" sidebar="false" showHeader="false" contentType="text/csv;charset=Shift-JIS#{!fileName}" readOnly="true" title="Csv Export">
<apex:repeat value="{!headers}" var="item">
<apex:outputText value="{!item}"/>
</apex:repeat>
<apex:repeat value="{!bodies}" var="items">
<apex:repeat value="{!items}" var="item">
<apex:outputText value="{!item}"/>
</apex:repeat>
</apex:repeat>
</apex:page>
public class ContactCsvExportController {
public String fileName {get; set;}
public List<String> headers {get; set;}
public List<List<String>> bodies {get; set;}
//CSV Export
public void export(){
fileName = 'ContactList.csv';
fileName = EncodingUtil.urlEncode(fileName, 'UTF-8');
// get recordId
Id recordId = ApexPages.currentPage().getParameters().get('id');
// get Contact
List<Contact> conList = [Select Id, Name, Title, Email, Phone, Department, Age__c, Birthdate, IsActive__c From Contact
Where AccountId =: recordId Order by Id];
// get label
List<String> labelList = new List<String>();
labelList.add('Id');
labelList.add(Schema.SObjectType.Contact.fields.Name.label);
labelList.add(Schema.SObjectType.Contact.fields.Title.label);
labelList.add(Schema.SObjectType.Contact.fields.Email.label);
labelList.add(Schema.SObjectType.Contact.fields.Phone.label);
labelList.add(Schema.SObjectType.Contact.fields.Department.label);
labelList.add(Schema.SObjectType.Contact.fields.Age__c.label);
labelList.add(Schema.SObjectType.Contact.fields.Birthdate.label);
labelList.add(Schema.SObjectType.Contact.fields.IsActive__c.label);
// CSV header
headers = new List<String>();
for(Integer i = 0; i < labelList.size(); i++){
if(i > 0){
headers.add(',');
}
headers.add('\"' + labelList.get(i) + '\"');
}
headers.add('\r\n');
// CSV bodies
bodies = new List<List<String>>();
for(Contact con : conList){
List<String> items = new List<String>();
items.add('\"' + con.Id + '\"');
items.add(',');
items.add(con.Name == null ? '' : '\"' + con.Name + '\"');
items.add(',');
items.add(con.Title == null ? '' : '\"' + con.Title + '\"');
items.add(',');
items.add(con.Email == null ? '' : '\"' + con.Email + '\"');
items.add(',');
items.add(con.Phone == null ? '' : '\"' + con.Phone + '\"');
items.add(',');
items.add(con.Department == null ? '' : '\"' + con.Department + '\"');
items.add(',');
items.add(con.Age__c == null ? '' : '\"' + con.Age__c + '\"');
items.add(',');
items.add(con.Birthdate == null ? '' : '\"' +con.Birthdate.format() + '\"');
items.add(',');
items.add(con.IsActive__c == null ? '' : '\"' + con.IsActive__c + '\"');
items.add('\r\n');
bodies.add(items);
}
}
}
コメント