2009-09-28 26 views
2

在JSF/RichFaces dataTable的每一行中都有布爾值複選框的正確方法是什麼?我想下面的代碼片段:在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> 

設置我customerListMap<Integer, Boolean> selectedCustomers。東西似乎工作得很好,除了顯然複選框是由一個索引的排序,而不是由ID實際,這是我的問題。

例如,當我打開上面的頁面並選中第一行中的複選框並按下我的「刪除」按鈕時,一切正常,頁面重新加載而沒有選定的客戶。但是如果我按「刷新」或「重新加載」,然後(並接受重新發送數據的瀏覽器警告),第一行中的現在爲的客戶將被刪除!

我該怎麼做才能讓複選框與選定的ID綁定?

回答

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這樣的第三方框架也增加了處理這類事情的能力。

+0

謝謝。雖然我不清楚這是如何工作的(或者會導致安全行狀態不一致),但重複表單提交和Seam的註釋很有幫助。我會嘗試Seam的''。 – 2009-09-29 10:53:06

+0

當表單被提交時,行將被索引解碼。由於隱藏字段中的id不再與服務器上該索引處的id相匹配,因此業務邏輯知道存在問題。使用id setter/getter與不同的成員變量一起工作來確定這一點。 – McDowell 2009-09-30 09:59:48

+0

好的,+1,謝謝。但是,如果我只是使用普通的HTML複選框,並將它們作爲包含ID的「List 」,它會更容易嗎? – 2009-09-30 10:31:29

相關問題