21

我有一个带有<h:dataTable>. 每行都有一个<h:selectBooleanCheckbox>. 如果选中复选框,则应在 bean 中设置相应行后面的对象。

  1. 我该怎么做呢?
  2. 如何在支持 bean 中获取选定的行或其数据?
  3. 或者这样做会更好<h:selectManyCheckbox>吗?
4

3 回答 3

53

最好的办法是将h:selectBooleanCheckbox值与代表行标识符类型的Map<RowId, Boolean>属性绑定。RowId让我们举一个例子,你有一个Item标识符属性id为 a的对象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

于 2010-03-26T16:18:32.003 回答
4

在以下示例中,我使用复选框来选择两个或更多产品,以允许用户使用 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>
于 2013-01-17T07:02:15.197 回答
1

发送参数的一种方法<h:selectBooleanCheckbox>是通过复选框的标题发送参数。在 中ValueChangeListener,您可以使用getAttributes().get("title"). 这在您希望将 id 值作为参数发送(而不是选定的行索引)的情况下很有帮助。

于 2011-10-11T17:46:11.753 回答