简体   繁体   English

如何使用<h:selectBooleanCheckbox>在<h:dataTable>或者<ui:repeat>选择多个项目?

[英]How to use <h:selectBooleanCheckbox> in <h:dataTable> or <ui:repeat> to select multiple items?

I have a Facelets page with a <h:dataTable> .我有一个带有<h:dataTable>的 Facelets 页面。 In each row there is a <h:selectBooleanCheckbox> .在每一行中都有一个<h:selectBooleanCheckbox> If the checkbox is selected the object behind the corresponding row should be set in the bean.如果选中复选框,则应在 bean 中设置相应行后面的对象。

  1. How do I do this?我该怎么做呢?
  2. How to get the selected rows or their data in a backing bean?如何在支持 bean 中获取选定的行或其数据?
  3. Or would it be better to do it with <h:selectManyCheckbox> ?或者使用<h:selectManyCheckbox>会更好吗?

Your best bet is to bind the <h:selectBooleanCheckbox> value with a Map<Item, Boolean> property where Item represents the object behind the corresponding row.最好的办法是将<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.
    }

    // ...
}

You see, the map is automatically filled with all table items as key and the checkbox value is automatically set as map value associated with the item as key.您会看到,地图自动填充所有表项作为键,复选框值自动设置为与作为键的项目关联的地图值。

This only requires that the Item#equals() and Item#hashCode() is properly implemented as per their contracts.这只需要Item#equals()Item#hashCode()根据他们的合同正确实施

If you can't guarantee that, then you'd better use a Map<RowId, Boolean> instead where RowId represents the type of the row identifier.如果不能保证,那么最好使用Map<RowId, Boolean>代替RowId表示行标识符的类型。 Let's take an example that you've a Item object whose identifier property id is a Long :让我们举个例子,你有一个Item对象,它的标识符属性idLong

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.
    }

    // ...
}

In the following example I am using checkboxes to select two or more products to allow the user to compare product specifications on a new web page using JSF 2.0.在以下示例中,我使用复选框来选择两个或更多产品,以允许用户使用 JSF 2.0 在新网页上比较产品规格。

It took me a good while to find the following problem (totally obvious now of course) so thought it worth a mention for those trying to use pagination with BalusC's code above (nice answer BalusC, much simpler than I ever imagined it would be).我花了很长时间才找到以下问题(当然现在很明显),所以认为对于那些试图在上面的 BalusC 代码中使用分页的人来说值得一提(BalusC 的答案很好,比我想象的要简单得多)。

If you are using pagination you will get nullpointers at the line:如果您使用分页,您将在该行获得空指针:

if (checked.get(item.getId())) if (checked.get(item.getId()))

-in BalusC's code above. -在上面的 BalusC 代码中。

This is because only displayed check boxes are added to the Map (doh; slap forehead).这是因为只有显示的复选框才会添加到地图中(doh;拍前额)。 For those products whose check boxes are never displayed, due to pagination, this line will result in a null pointer error and a check needs to be added to ignore these null pointers (assuming that all check boxes are unchecked on page load).对于那些复选框从不显示的产品,由于分页,此行将导致空指针错误,需要添加一个检查以忽略这些空指针(假设在页面加载时所有复选框都未选中)。 In order for the user to tick a check box then they need to display the pagination page so all works well there after.为了让用户勾选复选框,他们需要显示分页页面,以便之后一切正常。

If some or all of the check boxes are required to be ticked on first page load then this will be of no help to you...you will have to manually add those to the Map in order for them to be displayed correctly on page load.如果需要在第一页加载时勾选部分或全部复选框,那么这对您没有帮助...您必须手动将它们添加到地图中,以便它们在页面加载时正确显示.

Note: because I am using a JPA 'Entity class from database' object I also needed to use @Transient for the id in my ProductTbl Entity Class as all variables are considered columns in the database by JPA, by default, unless prefixed with @Transient.注意:因为我使用的是 JPA '来自数据库的实体类' 对象,所以我还需要在我的 ProductTbl 实体类中使用 @Transient 作为 ID,因为默认情况下,所有变量都被 JPA 视为数据库中的列,除非以 @Transient 为前缀. Also I am using a second link to reset the check boxes, which calls clearSelections(), and my 'submit' is a link calling compareSelectedProducts() rather than a Submit button.此外,我正在使用第二个链接来重置复选框,它调用 clearSelections(),我的“提交”是一个调用 compareSelectedProducts() 的链接,而不是一个提交按钮。

The full code is as follows:完整代码如下:

In the 'ProductTbl' Entity class derived from the database :在从数据库派生的“ProductTbl”实体类中:

@Transient
private Long id;

public Long getId()
{
    return id;
}

public void setId(Long id)
{
    this.id = id;
}

In the backing bean 'ProductSelection':在支持 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";
}

In the JSF Web page 'MainSearchResult.xhtml':在 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>

In the 'faces-config.xml' file:在“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>

One way to send in a parameter via <h:selectBooleanCheckbox> is to send it in via the title of the Checkbox.通过<h:selectBooleanCheckbox>发送参数的一种方法是通过 Checkbox 的标题发送参数。 In the ValueChangeListener , you can get it from the component using a getAttributes().get("title") .ValueChangeListener中,您可以使用getAttributes().get("title")从组件中获取它。 This helps in cases where you want to send an id value as a parameter (as opposed to the selected row index).这在您希望将 id 值作为参数发送(而不是选定的行索引)的情况下很有帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何选择多个行 <h:dataTable> 同 <h:selectBooleanCheckbox> - How to select multiple rows of <h:dataTable> with <h:selectBooleanCheckbox> 如何在ah:dataTable中的ah:dataTable中映射ah:selectBooleanCheckbox的值? - How to map the value of a h:selectBooleanCheckbox in a h:dataTable within a h:dataTable? ui:repeat中的数据表中的selectBooleanCheckbox - selectBooleanCheckbox in a DataTable in ui:repeat 如何使用位于数据表ah:列中的h:selectbooleancheckbox onclick方法来填充InputText? - How to use h:selectbooleancheckbox onclick method located in a h:column of a dataTable in order to fill an InputText? h:selectBooleanCheckBox对选择的操作 - h:selectBooleanCheckBox action on select 如何使用JSF的h:selectBooleanCheckbox和h:dataTable来获取选中的复选框而不提交页面内容? - How to use JSF's h:selectBooleanCheckbox with h:dataTable to get selected checkboxes without submitting the page content? 如何在ui中使用p:graphicImage和StreamedContent:repeat / h:dataTable / p:dataTable? - How to use p:graphicImage with StreamedContent inside ui:repeat/h:dataTable/p:dataTable? 使用h:selectBooleanCheckbox删除JSF数据表中的多行 - Using h:selectBooleanCheckbox to delete multiple rows in JSF datatable 如何在<h:dataTable>中使用<ui:include>? - How to use <ui:include> inside a <h:dataTable>? 如何在嵌套在 h:dataTable 中的 ui:repeat 中获取 h:outputText 以在数据表更新时进行更新? - How do I get h:outputText inside of a ui:repeat nested in h:dataTable to update when the datatable is updated?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM