PrimeFaces 5.0 で dataTable の列固定が実装されました。今まで行固定はあったのに、なんで列固定がないの?と困った方はわりといるのではないでしょうか。業務システムなんかだと、やけに表の列数が多くなって列固定を要求されることはままあるのでありがたいですね。
ただ、列固定をソート・行選択と組み合わせたところうまく行選択が動作しなくなってしまったので、メモっておきます(未解決)。
環境
- GlassFish 4.0
- PrimeFaces 5.0
コード
Backing Bean は以下のとおりです。 lombok 使ってます。
@Named(value = "tableBean") @ViewScoped public class TableBean implements Serializable { @Getter @Setter @EqualsAndHashCode @ToString @AllArgsConstructor @NoArgsConstructor public static class Row implements Serializable { private String id; private String value1; private String value2; private String value3; } @Getter @Setter private Row selectedRow; @Getter private final List<Row> rows; public TableBean() { rows = new ArrayList<>(); for (int i = 0; i < 10; i++) { rows.add(new Row(String.valueOf(i), "value1 of " + i, "value2 of " + i, "value3 of " + i)); } } public void handleRowSelect(SelectEvent event) { Row selected = (Row) event.getObject(); if (selected == null) { System.out.println("event object is null"); } else { System.out.println("event object: " + selected); } if (selectedRow == null) { System.out.println("selectedRow is null"); } else { System.out.println("selectedRow: " + selectedRow); } } }
xhtml は以下のとおりです。
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui"> <h:head> <title>DataTable</title> <meta charset="UTF-8" /> </h:head> <h:body> <h:form id="mainForm"> <p:outputLabel value="選択中: " /> <p:outputLabel id="selectedRowValue" value="#{tableBean.selectedRow}" /> <p:dataTable id="rowsTable" var="row" value="#{tableBean.rows}" rowKey="#{row.id}" selectionMode="single" selection="#{tableBean.selectedRow}" scrollable="true" frozenColumns="1"> <p:ajax event="rowSelect" listener="#{tableBean.handleRowSelect}" update=":mainForm:selectedRowValue" /> <p:column headerText="id" sortBy="#{row.id}"> <h:outputText value="#{row.id}" /> </p:column> <p:column headerText="value1" sortBy="#{row.value1}"> <h:outputText value="#{row.value1}" /> </p:column> <p:column headerText="value2" sortBy="#{row.value2}"> <h:outputText value="#{row.value2}" /> </p:column> <p:column headerText="value3" sortBy="#{row.value3}"> <h:outputText value="#{row.value3}" /> </p:column> </p:dataTable> </h:form> </h:body> </html>
動作
この状態で行をクリックすると、 Backing Bean の handleRowSelect
メソッドにより、コンソールに以下のように出力されます。
Info: event object: TableBean.Row(id=3, value1=value1 of 3, value2=value2 of 3, value3=value3 of 3) Info: selectedRow: TableBean.Row(id=3, value1=value1 of 3, value2=value2 of 3, value3=value3 of 3)
イベント引数と、 selection
属性で指定したフィールドいずれにも選択中の行オブジェクトが設定されていることがわかります。
しかし、列のソートを行った後で行をクリックすると出力は以下のようになります。
Info: event object is null Info: selectedRow is null
いずれも設定されていません。
Twitter でつぶやいていたところ、 @kikutaro_ さんに StackOverflow に同じような問題が上がっていることを教えていただきました。
コメントで I resolve 〜となっている方法を参考に、 dataTable 自体も更新するように xhtml の rowSelect イベントを以下のように書き換えてみます。コメントにある render とかいう属性は謎です。 rendered
の間違いかとも思いましたが、 rendered
に id 指定してなんか意味あるんでしょうか・・?
<p:ajax event="rowSelect" listener="#{tableBean.handleRowSelect}" update=":mainForm:selectedRowValue :mainForm:rowsTable" />
これをやると確かに選択状態は取れるようになるんですが、ソート直後の初回選択のみ選択状態が取れません。選択状態が取れないというより、選択列の見た目が変わらないので選択自体ができてないように見えます*1。一応 rendered
属性を update
属性と同じ値で設定してみましたが、特に何も起きませんでした。
なんかこういうのでハマると嫌ですね・・。
*1:解決にはこのへんがポイントな気がする?