我有一个带有<h:dataTable>
的Facelets页面。在每一行中都有一个<h:selectBooleanCheckbox>
。如果选中该复选框,则应在bean中设置相应行后面的对象。
<h:selectManyCheckbox>
答案 0 :(得分:52)
最好的办法是将h:selectBooleanCheckbox
值与Map<RowId, Boolean>
属性绑定,其中RowId
表示行标识符的类型。让我们举个例子,你有一个Item
对象,其标识符属性id
是Long
:
<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 Item {
private Long id;
// ...
}
和
public class Bean {
private Map<Long, Boolean> checked = new HashMap<Long, Boolean>();
private List<Item> items;
public void submit() {
List<Item> checkedItems = checked.entrySet().stream()
.filter(Entry::getKey)
.map(Entry::getValue)
.collect(Collectors.toList());
checked.clear(); // If necessary.
// Now do your thing with checkedItems.
}
// ...
}
您会看到,地图会自动填充所有表项的id
作为键,并且复选框值会自动设置为与项id
关联的地图值作为键。
答案 1 :(得分:4)
在以下示例中,我使用复选框选择两个或更多产品,以允许用户使用JSF 2.0在新网页上比较产品规格。
我花了很长时间才找到以下问题(当然现在完全显而易见)所以认为值得一提的是那些尝试使用上面BalusC代码的分页(很好的答案BalusC,比我想象的要简单得多)是)。
如果您正在使用分页,您将在该行获得无效指示符:
if(checked.get(item.getId()))
-in BalusC上面的代码。
这是因为只有显示的复选框被添加到Map(doh; slap额头)。 对于那些由于分页而从未显示复选框的产品,此行将导致空指针错误,并且需要添加检查以忽略这些空指针(假设在页面加载时未选中所有复选框)。为了让用户勾选一个复选框,他们需要显示分页页面,以便一切顺利。
如果首页加载时需要勾选部分或全部复选框,那么这对您没有帮助......您必须手动将这些复选框添加到地图中才能正确显示在页面加载。
注意:因为我正在使用JPA'来自数据库'对象的实体类,所以我还需要在我的ProductTbl实体类中使用@Transient作为id,因为默认情况下,所有变量都被JPA视为数据库中的列,除非有前缀与@Transient。此外,我使用第二个链接重置复选框,调用clearSelections(),我的'submit'是一个调用compareSelectedProducts()而不是Submit按钮的链接。
完整代码如下:
在从数据库派生的'ProductTbl'Entity类中:
@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>
答案 2 :(得分:1)
通过<h:selectBooleanCheckbox>
发送参数的一种方法是通过复选框的标题发送。在ValueChangeListener
中,您可以使用getAttributes().get("title")
从组件中获取它。这有助于您希望将id值作为参数发送(与选定的行索引相反)。