Как использовать <h: selectBooleanCheckbox> в <h: dataTable> или <ui: repeat> для выбора нескольких элементов? - PullRequest
20 голосов
/ 26 марта 2010

У меня есть страница Facelets с <h:dataTable>. В каждом ряду есть <h:selectBooleanCheckbox>. Если флажок установлен, объект за соответствующей строкой должен быть установлен в компоненте.

  1. Как мне это сделать?
  2. Как получить выбранные строки или их данные в базовом компоненте?
  3. Или лучше сделать это с <h:selectManyCheckbox>?

Ответы [ 3 ]

52 голосов
/ 26 марта 2010

Лучше всего связывать значение 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 в качестве ключа.

4 голосов
/ 17 января 2013

В следующем примере я использую флажки, чтобы выбрать два или более продуктов, чтобы позволить пользователю сравнивать спецификации продуктов на новой веб-странице с использованием JSF 2.0.

Мне потребовалось много времени, чтобы найти следующую проблему (теперь, очевидно, совершенно очевидную), поэтому я подумал, что стоит упомянуть тех, кто пытается использовать нумерацию страниц с кодом BalusC, приведенным выше (хороший ответ BalusC, гораздо проще, чем я мог себе представить быть).

Если вы используете нумерацию страниц, вы получите нулевые точки в строке:

if (check.get (item.getId ()))

- в коде BalusC выше.

Это потому, что только отображаемые флажки добавляются на карту (doh; хлопать по лбу). Для тех продуктов, чьи флажки никогда не отображаются, из-за разбиения на страницы эта строка приведет к ошибке нулевого указателя, и необходимо добавить проверку, чтобы игнорировать эти нулевые указатели (при условии, что все флажки сняты при загрузке страницы). Для того, чтобы пользователь установил флажок, ему нужно отобразить страницу разбиения на страницы, чтобы после этого все работало хорошо.

Если некоторые или все флажки должны быть отмечены при загрузке первой страницы, это не поможет вам ... вам придется вручную добавить их на карту, чтобы они отображались правильно при загрузке страницы.

Примечание: поскольку я использую объект JPA «Класс сущности из базы данных», мне также нужно было использовать @Transient для идентификатора в моем классе сущностей ProductTbl, так как все переменные по умолчанию считаются столбцами в базе данных JPA, если только не указан префикс с @Transient. Кроме того, я использую вторую ссылку для сброса флажков, которая вызывает clearSelections (), и моя 'submit' - это ссылка, вызывающая CompareSelectedProducts (), а не кнопка Submit.

Полный код выглядит следующим образом:

В классе сущностей ProductTbl, полученном из базы данных:

@Transient
private Long id;

public Long getId()
{
    return id;
}

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

В бобе '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>

В файлеface-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>
1 голос
/ 11 октября 2011

Один из способов отправить параметр через <h:selectBooleanCheckbox> - отправить его через заголовок флажка. В ValueChangeListener вы можете получить его из компонента, используя getAttributes().get("title"). Это помогает в тех случаях, когда вы хотите отправить значение идентификатора в качестве параметра (в отличие от выбранного индекса строки).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...