![](/img/trans.png)
[英]How to select multiple rows of <h:dataTable> with <h:selectBooleanCheckbox>
[英]How to use <h:selectBooleanCheckbox> in <h:dataTable> or <ui:repeat> to select multiple items?
我有一個帶有<h:dataTable>
的 Facelets 頁面。 在每一行中都有一個<h:selectBooleanCheckbox>
。 如果選中復選框,則應在 bean 中設置相應行后面的對象。
<h:selectManyCheckbox>
會更好嗎?最好的辦法是將<h:selectBooleanCheckbox>
值與Map<Item, Boolean>
屬性綁定,其中Item
表示相應行后面的對象。
<h:dataTable value="#{bean.items}" var="item">
<h:column>
<h:selectBooleanCheckbox value="#{bean.checked[item]}" />
</h:column>
...
</h:dataTable>
<h:commandButton value="submit" action="#{bean.submit}" />
public class Bean {
private Map<Item, Boolean> checked = new HashMap<Item, Boolean>();
private List<Item> items;
public void submit() {
List<Item> selectedItems = checked.entrySet().stream()
.filter(Entry::getValue)
.map(Entry::getKey)
.collect(Collectors.toList());
checked.clear(); // If necessary.
// Now do your thing with selectedItems.
}
// ...
}
您會看到,地圖自動填充所有表項作為鍵,復選框值自動設置為與作為鍵的項目關聯的地圖值。
這只需要Item#equals()
和Item#hashCode()
根據他們的合同正確實施。
如果不能保證,那么最好使用Map<RowId, Boolean>
代替RowId
表示行標識符的類型。 讓我們舉個例子,你有一個Item
對象,它的標識符屬性id
是Long
:
public class Item {
private Long id;
// ...
}
<h:dataTable value="#{bean.items}" var="item">
<h:column>
<h:selectBooleanCheckbox value="#{bean.checked[item.id]}" />
</h:column>
...
</h:dataTable>
<h:commandButton value="submit" action="#{bean.submit}" />
public class Bean {
private Map<Long, Boolean> checked = new HashMap<Long, Boolean>();
private List<Item> items;
public void submit() {
List<Item> selectedItems = items.stream()
.filter(item -> checked.get(item.getId()))
.collect(Collectors.toList());
checked.clear(); // If necessary.
// Now do your thing with selectedItems.
}
// ...
}
在以下示例中,我使用復選框來選擇兩個或更多產品,以允許用戶使用 JSF 2.0 在新網頁上比較產品規格。
我花了很長時間才找到以下問題(當然現在很明顯),所以認為對於那些試圖在上面的 BalusC 代碼中使用分頁的人來說值得一提(BalusC 的答案很好,比我想象的要簡單得多)。
如果您使用分頁,您將在該行獲得空指針:
if (checked.get(item.getId()))
-在上面的 BalusC 代碼中。
這是因為只有顯示的復選框才會添加到地圖中(doh;拍前額)。 對於那些復選框從不顯示的產品,由於分頁,此行將導致空指針錯誤,需要添加一個檢查以忽略這些空指針(假設在頁面加載時所有復選框都未選中)。 為了讓用戶勾選復選框,他們需要顯示分頁頁面,以便之后一切正常。
如果需要在第一頁加載時勾選部分或全部復選框,那么這對您沒有幫助...您必須手動將它們添加到地圖中,以便它們在頁面加載時正確顯示.
注意:因為我使用的是 JPA '來自數據庫的實體類' 對象,所以我還需要在我的 ProductTbl 實體類中使用 @Transient 作為 ID,因為默認情況下,所有變量都被 JPA 視為數據庫中的列,除非以 @Transient 為前綴. 此外,我正在使用第二個鏈接來重置復選框,它調用 clearSelections(),我的“提交”是一個調用 compareSelectedProducts() 的鏈接,而不是一個提交按鈕。
完整代碼如下:
在從數據庫派生的“ProductTbl”實體類中:
@Transient
private Long id;
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
在支持 bean 'ProductSelection' 中:
private Map<Long, Boolean> checked = new HashMap<Long, Boolean>();
private String errorMessage = "";
// List of all products.
private List<ProductTbl> products;
// List of products to compare.
private List<ProductTbl> compareProducts;
// Setters and getters for above...
public String compareSelectedProducts()
{
// Reset selected products store.
compareProducts = new ArrayList();
for (ProductTbl item: products)
{
// If there is a checkbox mapping for the current product then...
if(checked.get(item.getId()) != null)
{
// If checkbox is ticked then...
if (checked.get(item.getId()))
{
// Add product to list of products to be compared.
compareProducts.add(item);
}
}
}
if(compareProducts.isEmpty())
{
// Error message that is displayed in the 'ErrorPage.xhtml' file.
errorMessage = "No Products selected to compare specifications. Select two or more products by ticking the check box in the second column 'Cmpr'";
return "process_ErrorPage";
}
// Rest of code to get product specification data ready to be displayed.
return "process_CompareSelected";
}
public String clearSelections()
{
// Untick all checkbox selections.
checked.clear();
return "process_MainSearchResult";
}
在 JSF 網頁“MainSearchResult.xhtml”中:
<h:commandLink action="#{productSelection.compareSelectedProducts()}" value="Cmpr Specification Comparison Table" />
<h:commandLink action="#{productSelection.clearSelections()}" value="Clear Selected" />
<h:dataTable value="#{productSelection.products}" rows="#{productSelection.numberRowsToDisplay}" first="#{productSelection.rowStart}" var="item" headerClass="table-header" >
<h:column>
<f:facet name="header">
<h:outputText style="font-size:12px" value="Cmpr" />
</f:facet>
<div style="text-align:center;" >
<h:selectBooleanCheckbox value="#{productSelection.checked[item.id]}" />
</div>
</h:column>
</h:dataTable>
在“faces-config.xml”文件中:
<navigation-rule>
<navigation-case>
<from-outcome>process_MainSearchResult</from-outcome>
<to-view-id>/MainSearchResult.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<navigation-case>
<from-outcome>process_CompareSelected</from-outcome>
<to-view-id>/CompareSelected.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<navigation-case>
<from-outcome>process_ErrorPage</from-outcome>
<to-view-id>/ErrorPage.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
通過<h:selectBooleanCheckbox>
發送參數的一種方法是通過 Checkbox 的標題發送參數。 在ValueChangeListener
中,您可以使用getAttributes().get("title")
從組件中獲取它。 這在您希望將 id 值作為參數發送(而不是選定的行索引)的情況下很有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.