在JSF / RichFaces`dataTable`中有一个布尔复选框的正确方法是什么?

时间:2009-09-28 09:52:48

标签: java jsf java-ee

在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绑定?

1 个答案:

答案 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这样的第三方框架也为这类事情添加了处理。