Oracle ADF Faces <af:table> 提供 detailStamp 面板支援主從式明細展開。本文示範如何透過 disclosureListener 控制明細顯示邏輯,並進階實作「單一展開」:展開新行時自動關閉前一行。
<af:table value="#{tableTest.allData}" var="data"
disclosureListener="#{tableTest.showDetails}"
varStatus="vs" banding="none">
<af:column sortable="true" formatType="icon" ...>
<f:facet name="header"><af:outputText value="NO."/></f:facet>
<af:outputText value="#{data.column1}"/>
</af:column>
<af:column ...><f:facet name="header"><af:outputText value="Last Name"/></f:facet>
<af:outputText value="#{data.column2}"/></af:column>
<af:column ...><f:facet name="header"><af:outputText value="First Name"/></f:facet>
<af:outputText value="#{data.column3}"/></af:column>
<f:facet name="detailStamp">
<af:panelGroup layout="vertical">
<af:outputText rendered="#{tableTest.showDetail}" value="#{data.detail}"/>
<af:outputText rendered="#{tableTest.showDetail}" value="#{data.detail}"/>
<af:outputText rendered="#{tableTest.showDetail}" value="#{data.detail}"/>
</af:panelGroup>
</f:facet>
</af:table>
public class TableDataBackBean {
private List<TableData> allData = new ArrayList<>();
private boolean showDetail = false;
public TableDataBackBean() {
allData.add(new TableData("1","vincent","ma","vincent ma detail"));
allData.add(new TableData("2","barry","fan","barry fan detail"));
// ... 更多測試資料
}
public void showDetails(DisclosureEvent event) {
if (event.isExpanded()) this.showDetail = true;
}
// getter/setter 省略
}
private String oldValue = "";
public void showDetails(DisclosureEvent disclosureEvent) {
CoreTable table = (CoreTable) disclosureEvent.getComponent();
if (disclosureEvent.isExpanded()) this.showDetail = true;
RowKeySet rowKeySet = table.getDisclosureState();
Set<Object> keySet = rowKeySet.getKeySet();
Iterator<Object> iter = keySet.iterator();
if (keySet.size() == 2) { // 使用者剛展開第二行
while (iter.hasNext()) {
String temp = (String) iter.next();
if (!temp.equals(oldValue)) { // 找到新展開的行
oldValue = temp;
break;
}
}
keySet.clear();
keySet.add(oldValue); // 只保留新行
} else if (keySet.size() == 1) { // 單行展開或收合後剩一行
while (iter.hasNext()) oldValue = (String) iter.next();
keySet.add(oldValue);
}
table.setDisclosureState(rowKeySet);
}
| API | 用途 |
|---|---|
DisclosureEvent.isExpanded() | 判斷使用者動作是展開還是收合 |
CoreTable.getDisclosureState() | 取得目前展開行的 RowKeySet |
RowKeySet.getKeySet() | 取得行鍵值集合 (可迭代) |
CoreTable.setDisclosureState() | 強制設定展開狀態,觸發 UI 更新 |
detailStamp 內組件使用 rendered="#{bean.showDetail}" 控制可見性,需配合 listener 更新旗標rowBandingInterval 與 fetchSize 優化渲染