最近、BalusC によって書かれた多くのスタックオーバーフローの回答のおかげで、複合コンポーネントの代替として Facelet タグ ファイルを発見し、PrimeFaces dataTable の問題を解決するためにそれらを使用しています。p:dataTable のさまざまな属性の束をコンポーネント/facelet に標準化したいのですが、「selectionMode」のようにオプションにしたいいくつかの属性は空の文字列に評価できません。それ以外の場合、コンポーネントは壊れています ( http:/を参照) /forum.primefaces.org/viewtopic.php?f=3&t=29066 )。Facelet タグ ファイルを使用して、オプションの属性が存在するかどうかに応じて、代替の p:dataTables を条件付きでレンダリングしました。
ただし、dataTable にネストされた AjaxBehaviors の EL 式に新しい問題が発生しました。
/WEB-INF/tags/dataTable.xhtml の短縮例:
<ui:composition>
<p:dataTable var="row"
value="#{value}"
filteredValue="#{state.filteredValue}"
first="#{state.first}"
rows="#{state.rows}">
<f:event type="preRenderComponent" listener="#{state.onPreRenderComponent}"/>
<p:ajax event="page" listener="#{state.onPage}"/>
<p:ajax event="sort" listener="#{state.onSort}"/>
<p:ajax event="filter" listener="#{state.onFilter}"/>
<ui:insert/>
</p:dataTable>
</ui:composition>
タグファイルを利用したページの例:
<my:dataTable value="#{mybean.list}" state="#{mybean.state}">
<p:column headerText="Name"
sortBy="#{row.name}"
filterBy="#{row.name}">
#{row.name}
</p:column>
</my:dataTable>
3 つの p:ajax イベントが実行されるまで、私の「状態」式は正常に処理されているようです。イベントが中断され (つまり、ページング/並べ替えが無効になり)、次のスタック トレースがログに記録されます。
12:36:06,660 WARNING [javax.enterprise.resource.webcontainer.jsf.lifecycle] (http--0.0.0.0-8080-3) Target Unreachable, identifier 'state' resolved to null: javax.el.PropertyNotFoundException: Target Unreachable, identifier 'state' resolved to null
at org.apache.el.parser.AstValue.getTarget(AstValue.java:98) [jbossweb-7.0.13.Final.jar:]
org.apache.el.parser.AstValue.invoke(AstValue.java:244) [jbossweb-7.0.13.Final.jar:]
org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278) [jbossweb-7.0.13.Final.jar:]
org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:39) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
org.primefaces.component.behavior.ajax.AjaxBehaviorListenerImpl.processCustomListener(AjaxBehaviorListenerImpl.java:70) [primefaces-3.5.jar:]
org.primefaces.component.behavior.ajax.AjaxBehaviorListenerImpl.processArgListener(AjaxBehaviorListenerImpl.java:59) [primefaces-3.5.jar:]
org.primefaces.component.behavior.ajax.AjaxBehaviorListenerImpl.processAjaxBehavior(AjaxBehaviorListenerImpl.java:47) [primefaces-3.5.jar:]
org.primefaces.event.data.SortEvent.processListener(SortEvent.java:45) [primefaces-3.5.jar:]
javax.faces.component.behavior.BehaviorBase.broadcast(BehaviorBase.java:106) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
複合コンポーネントとして実装された場合、この問題は存在しません。つまり、これらの AjaxBehavior で #{cc.attrs.state} 関数を正しく使用することです。
Facelet タグ ファイル、その属性、EL 式の範囲とライフサイクルについての私の理解は限られています。p:ajax でバグに遭遇したのでしょうか、それとも私の「状態」式は初期段階でのみ有効ですか?
参考までに、「mybean」および「state」オブジェクトは CDI および CODI を使用し、次のように定義されます。
@Named("mybean")
@ViewAccessScoped
@SuppressWarnings("serial")
public class MyBean implements Serializable {
private List<SomeEntiy> list;
@Inject
private DataTableState state;
public List<SomeEntity> getList() {
return list;
}
public DataTableState getState() {
return state;
}
// Details about loading the list hidden
}
...と...
@Dependent
@SuppressWarnings("serial")
public class DataTableState implements Serializable {
private final static Logger log = Logger.getLogger(DataTableState.class.getName());
private List<?> filteredValue;
private int first;
private int rows = 20;
private Map<String,String> filters = new HashMap<String,String>();
private ValueExpression sortBy;
private String sortOrder;
public List<?> getFilteredValue() {
return filteredValue;
}
public void setFilteredValue(List<?> filteredValue) {
this.filteredValue = filteredValue;
if (filteredValue == null && !filters.isEmpty()) {
if (log.isLoggable(Level.FINEST))
log.finest("setFilteredValue: Resetting filters");
filters.clear();
}
}
public int getFirst() {
return first;
}
public void setFirst(int first) {
this.first = first;
}
public int getRows() {
return rows;
}
public void setRows(int rows) {
if (log.isLoggable(Level.FINEST))
log.finest("setRows: " + rows);
this.rows = rows;
}
public Map<String,String> getFilters() {
return filters;
}
public void onPreRenderComponent(ComponentSystemEvent event) {
DataTable source = (DataTable) event.getSource();
if (sortBy != null)
source.setValueExpression("sortBy", sortBy);
if (sortOrder != null)
source.setSortOrder(sortOrder);
}
public void onPage(PageEvent event) {
DataTable source = (DataTable) event.getSource();
first = source.getFirst();
}
public void onSort(SortEvent event) {
UIColumn column = event.getSortColumn();
sortBy = column.getValueExpression("sortBy");
if (event.isAscending())
sortOrder = "ascending";
else
sortOrder = "descending";
}
public void onFilter(FilterEvent event) {
Map<String,String> filters = event.getFilters();
this.filters.clear();
this.filters.putAll(filters);
}
}