一覧をソートしてみる
ガストロバル パロマ+1のハンバーグランチ。
どう食べれば良いか1分ほど悩んだ。
一覧のヘッダをクリックしたときに、クリックした項目でソートする処理を作ってみた。
姓項目を昇順でソートした状態
- ソート結果はクエリを実行し取得
- ヘッダの文字列部分はApexコンポーネントを使用
- どの項目を、昇順or降順でソートしているかの状態を保持するクラスを作成
- これを、項目のAPI参照名をキーにしたMapで管理
ページ
<apex:page controller="SortListController" action="{!doInit}"> <apex:form > <apex:pageBlock title="取引先責任者一覧"> <apex:pageBlockTable value="{!contacts}" var="cont" id="dataTable"> <apex:column> <apex:facet name="header"> <c:SortHeader headerLabel="{!$ObjectType.Contact.Fields.LastName.Label}" sortMethod="{!doSort}" sortColumn="LastName" sortIcon="{!sortStatusMap['LastName'].sortIcon}" rerenderId="dataTable" /> </apex:facet> <apex:outputField value="{!cont.LastName}" /> </apex:column> <apex:column> <apex:facet name="header"> <c:SortHeader headerLabel="{!$ObjectType.Contact.Fields.FirstName.Label}" sortMethod="{!doSort}" sortColumn="FirstName" sortIcon="{!sortStatusMap['FirstName'].sortIcon}" rerenderId="dataTable" /> </apex:facet> <apex:outputField value="{!cont.FirstName}" /> </apex:column> <apex:column> <apex:facet name="header"> <c:SortHeader headerLabel="{!$ObjectType.Contact.Fields.Title.Label}" sortMethod="{!doSort}" sortColumn="Title" sortIcon="{!sortStatusMap['Title'].sortIcon}" rerenderId="dataTable" /> </apex:facet> <apex:outputField value="{!cont.Title}" /> </apex:column> <apex:column> <apex:facet name="header"> <c:SortHeader headerLabel="{!$ObjectType.Contact.Fields.Phone.Label}" sortMethod="{!doSort}" sortColumn="Phone" sortIcon="{!sortStatusMap['Phone'].sortIcon}" rerenderId="dataTable" /> </apex:facet> <apex:outputField value="{!cont.Phone}" /> </apex:column> <apex:column> <apex:facet name="header"> <c:SortHeader headerLabel="{!$ObjectType.Contact.Fields.Email.Label}" sortMethod="{!doSort}" sortColumn="Email" sortIcon="{!sortStatusMap['Email'].sortIcon}" rerenderId="dataTable" /> </apex:facet> <apex:outputField value="{!cont.Email}" /> </apex:column> </apex:pageBlockTable> </apex:pageBlock> </apex:form> </apex:page>
コンポーネント
<apex:component > <apex:attribute name="headerLabel" type="String" description="ヘッダに表示する文字列" /> <apex:attribute name="sortMethod" type="ApexPages.Action" description="ヘッダ文字列押下時に実行するメソッド" required="true" /> <apex:attribute name="sortColumn" type="String" description="ソート対象のカラム" required="true" /> <apex:attribute name="sortIcon" type="String" description="項目の右側に表示するソート方向を示す文字" required="true" /> <apex:attribute name="rerenderId" type="String" description="ヘッダ文字列押下時の再描画領域" /> <apex:commandLink value="{!headerLabel}" action="{!sortMethod}" reRender="{!rerenderId}" > <apex:param value="{!sortColumn}" name="sortColumn" /> </apex:commandLink> <apex:outputText value="{!sortIcon}" style="font-size: 80%; font-weight: normal;" /> </apex:component>
コントローラ
public with sharing class SortListController { /** ベースのSELECT文 */ private String baseQuery = 'SELECT Id, FirstName, LastName, Title, Phone, Email FROM Contact '; /** 表示データ */ public List<Contact> contacts {get; set;} /** カラムごとのソート状態 */ public Map<String, SortStatus> sortStatusMap {get; set;} /** * コンストラクタ */ public SortListController() { initSortStatus(); } /** * 初期処理 */ public PageReference doInit() { this.contacts = Database.query(this.baseQuery); return null; } /** * ソート(ヘッダ押下時) */ public PageReference doSort() { // ソート対象のカラムを取得 String sortColumn = ApexPages.currentPage().getParameters().get('sortColumn'); // ソート状態を変更 changeSortStatus(sortColumn); // ソート条件を付加してデータ取得 String query = this.baseQuery; query += 'ORDER BY ' + sortColumn + ' ' + this.sortStatusMap.get(sortColumn).sortWord; this.contacts = Database.query(query); return null; } /** * ソート状態の初期化 */ private void initSortStatus() { this.sortStatusMap = new Map<String, SortStatus> { 'FirstName' => new SortStatus(), 'LastName' => new SortStatus(), 'Title' => new SortStatus(), 'Phone' => new SortStatus(), 'Email' => new SortStatus() }; } /** * ソート状態の変更 */ private void changeSortStatus(String sortColumn){ for (String key : this.sortStatusMap.keySet()) { if (key == sortColumn) { this.sortStatusMap.get(key).change(); } else { this.sortStatusMap.get(key).init(); } } } }
ソート状態を保持するクラス
/** * ソート状態を保持するクラス */ public class SortStatus { /** ソート順 定義:ソートなし */ public static Integer SORT_ORDER_NONE = 0; /** ソート順 定義:昇順ソート */ public static Integer SORT_ORDER_ASC = 1; /** ソート順 定義:降順ソート */ public static Integer SORT_ORDER_DESC = 2; /** ソート順 */ public Integer sortOrder {get; set;} /** 一覧のヘッダに表示するソート方向を示す文字(↑↓など) */ public String sortIcon {get; set;} /** SOQLのソート句 */ public String sortWord {get; set;} /** * コンストラクタ */ public SortStatus() { init(); } /** * メンバ変数初期化 */ public void init() { this.sortOrder = SORT_ORDER_NONE; this.sortIcon = null; this.sortWord = null; } /** * ソート順の変更 */ public void change() { if (this.sortOrder == SORT_ORDER_NONE || this.sortOrder == SORT_ORDER_DESC) { this.sortOrder = SORT_ORDER_ASC; this.sortIcon = '↑'; this.sortWord = 'ASC'; } else if (this.sortOrder == SORT_ORDER_ASC) { this.sortOrder = SORT_ORDER_DESC; this.sortIcon = '↓'; this.sortWord = 'DESC'; } else { this.sortOrder = SORT_ORDER_NONE; this.sortIcon = null; this.sortWord = null; } } }
実装時の驚き
- apex:attributeにメソッドを渡せる
- VisualforceでMapを使える