web-dev-qa-db-ja.com

<h:dataTable>または<ui:repeat>で<h:selectBooleanCheckbox>を使用して複数のアイテムを選択する方法

<h:dataTable>のFaceletsページがあります。各行には<h:selectBooleanCheckbox>があります。チェックボックスが選択されている場合、対応する行の後ろのオブジェクトをBeanに設定する必要があります。

  1. どうすればよいですか?
  2. 選択した行またはそれらのデータをバッキングBeanで取得する方法は?
  3. それとも、<h:selectManyCheckbox>を使用した方がよいでしょうか?
20
c0d3x

最善の策は、h:selectBooleanCheckbox値をMap<RowId, Boolean>プロパティにバインドすることです。ここで、RowIdは行識別子のタイプを表します。識別子プロパティItemidである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に関連付けられたマップ値としてキーとして自動的に設定されます。

52
BalusC

次の例では、チェックボックスを使用して2つ以上の製品を選択し、ユーザーがJSF 2.0を使用して新しいWebページで製品仕様を比較できるようにしています。

次の問題(もちろん今は完全に明らかです)を見つけるのにかなりの時間がかかりましたので、上記のBalusCのコードでページ分割を使用しようとする人には言及する価値があると思いました(正解BalusC、これまで想像していたよりもはるかに単純です)。

ページネーションを使用している場合は、次の行にnullポインタが表示されます。

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

-上記のBalusCのコード。

これは、表示されたチェックボックスのみがマップに追加されているためです(doh、スラップ額)。ページ付けが原因でチェックボックスが表示されない製品の場合、この行によりnullポインターエラーが発生し、これらのnullポインターを無視するためにチェックを追加する必要があります(ページの読み込み時にすべてのチェックボックスがオフになっている場合)。ユーザーがチェックボックスをオンにするには、ページ付けページを表示して、その後すべてが適切に機能するようにする必要があります。

最初のページの読み込み時にチェックボックスの一部またはすべてをオンにする必要がある場合、これは役に立ちません...ページの読み込み時に正しく表示されるようにするには、手動でマップに追加する必要があります。 。

注:JPA 'データベースのエンティティクラス'オブジェクトを使用しているため、@ Transientが前に付いていない限り、すべての変数はデフォルトでJPAによってデータベースの列と見なされるため、ProductTblエンティティクラスのIDに@Transientも使用する必要がありました。 。また、チェックボックスをリセットするために2番目のリンクを使用しています。これは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 Webページ '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>
4
Robbie62

_<h:selectBooleanCheckbox>_を介してパラメータを送信する1つの方法は、チェックボックスのタイトルを介して送信することです。 ValueChangeListenerでは、getAttributes().get("title")を使用してコンポーネントから取得できます。これは、(選択した行インデックスではなく)パラメーターとしてid値を送信する場合に役立ちます。

1
Mallika