在JSF / RichFaces dataTable
的每一行中有一个布尔复选框的正确方法是什么?我尝试了以下代码段:
<rich:dataTable id="customerList"
var="_customer"
value="#{customerList.resultList}"
rendered="#{not empty customerList.resultList}" >
<h:column>
<h:selectBooleanCheckbox
value="#{customerList.selectedCustomers[_customer.id]}" />
</h:column>
...
</rich:dataTable>
我将customerList
设置为Map<Integer, Boolean> selectedCustomers
。事情似乎运作良好,除了显然复选框是由排序索引映射,而不是实际上由ID映射,这导致我的问题。
例如,当我打开上面的页面并检查第一行中的复选框并按下“删除”按钮时,一切正常,并且在没有所选客户的情况下重新加载页面。但是,如果我按“刷新”或“重新加载”,然后(并接受重新发送数据的浏览器警告),第一行中现在的客户将被删除!
如何才能将复选框与所选ID绑定?
答案 0 :(得分:3)
如果您只想处理刷新,请查看导航规则中的redirect
选项。
<navigation-rule>
<display-name>navBack</display-name>
<from-view-id>/navBack.jsp</from-view-id>
<navigation-case>
<from-outcome>navTo</from-outcome>
<to-view-id>/navTo.jsp</to-view-id>
<redirect />
</navigation-case>
</navigation-rule>
如果您也想处理后退按钮和多个窗口的情况,请继续阅读。
您可以使用隐藏字段和行级工件检测到这一点。基本上,您会根据提交表单时收到的ID检查发送给客户端的ID。
public class SafeRow {
private final String rowId;
private String rowIdClient;
private String name;
private boolean delete;
public SafeRow(String name) {
this();
this.name = name;
}
public SafeRow() {
rowId = UUID.randomUUID().toString();
}
public String getRowId() { return rowId; }
public void setRowId(String rowIdClient) { this.rowIdClient = rowIdClient; }
public boolean isStateConsistent() {
return rowId.equals(rowIdClient);
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public boolean isDelete() { return delete; }
public void setDelete(boolean delete) { this.delete = delete; }
}
表格数据:
public class SafeUpdateBean {
private final List<SafeRow> data = new ArrayList<SafeRow>();
public SafeUpdateBean() {
data.add(new SafeRow("Bill"));
data.add(new SafeRow("Ben"));
data.add(new SafeRow("Sue"));
}
public List<SafeRow> getData() { return data; }
public String deleteSelected() {
Iterator<SafeRow> all = data.iterator();
while (all.hasNext()) {
SafeRow row = all.next();
if (!row.isStateConsistent()) {
System.err.println("Caught inconsistency on " + row.getRowId());
} else if (row.isDelete()) {
all.remove();
}
}
return null;
}
}
观点:
<h:form>
<h:dataTable value="#{safeUpdateBean.data}" var="row">
<h:column>
<h:inputHidden value="#{row.rowId}" />
<h:selectBooleanCheckbox value="#{row.delete}" />
<h:outputText value="#{row.name}" />
</h:column>
</h:dataTable>
<h:commandButton value="delete selected"
action="#{safeUpdateBean.deleteSelected}" />
</h:form>
这个演示代码使用了一个简单的会话bean,但希望很清楚如何使它适应更合理的东西。这不是您唯一能做的事情 - 例如,您可以执行更一般的重复表单提交。像Seam这样的第三方框架也为这类事情添加了处理。