19

Tôi có trang Facelets với <h:dataTable>. Trong mỗi hàng có <h:selectBooleanCheckbox>. Nếu hộp kiểm được chọn, đối tượng phía sau hàng tương ứng sẽ được đặt trong bean.Cách sử dụng <h: selectBooleanCheckbox> trong <h:dataTable> hoặc <ui:repeat> để chọn nhiều mục?

  1. Làm cách nào để thực hiện việc này?
  2. Làm cách nào để có được các hàng đã chọn hoặc dữ liệu của chúng trong bean sao lưu?
  3. Hoặc sẽ tốt hơn nếu bạn làm điều đó với <h:selectManyCheckbox>?
+0

Hi BalusC, này không hoạt động trên pagination, Bất kỳ Gợi ý? –

Trả lời

48

Đặt cược tốt nhất của bạn là ràng buộc giá trị h:selectBooleanCheckbox với thuộc tính Map<RowId, Boolean> nơi RowId đại diện cho loại định danh hàng. Chúng ta hãy lấy một ví dụ mà bạn đã một đối tượng Item mà nhận dạng tài sản id là một 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}" /> 

mà là để được sử dụng kết hợp với:

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

    // ... 
} 

Bạn thấy đấy, bản đồ được tự động điền vào các id của tất cả các mục bảng dưới dạng khóa và giá trị hộp kiểm là tự động cally được đặt làm giá trị bản đồ được liên kết với mục id làm khóa.

+0

Sẽ không còn dễ dàng hơn khi sử dụng một 'Bản đồ' loại '' vì vậy bạn chỉ cần lặp lại bản đồ thay vì toàn bộ danh sách? –

+0

@Markus: điều đó là không thể. '' chỉ hỗ trợ các giá trị 'boolean' hoặc' Boolean'. – BalusC

+1

là bảng dữ liệu và nút phải ở trong cùng một hình thức? bạn có thể xin vui lòng gửi thêm chi tiết cho các bên xem, hoặc chỉ có các nút nên được trong một hình thức. –

1

Một cách để gửi thông số qua <h:selectBooleanCheckbox> là gửi thông qua tiêu đề của hộp kiểm. Trong số ValueChangeListener, bạn có thể lấy nó từ thành phần bằng cách sử dụng getAttributes().get("title"). Điều này giúp trong trường hợp bạn muốn gửi một giá trị id làm tham số (trái với chỉ số hàng đã chọn).

+0

Tôi không chắc chắn ý bạn là gì với "trái với chỉ số hàng đã chọn", nhưng nếu bạn đang nhắm mục tiêu vào câu trả lời của tôi, sau đó xin lưu ý rằng tôi không đi qua các chỉ mục hàng xung quanh. Chỉ các ID của các mục đã chọn. – BalusC

3

Trong ví dụ sau, tôi đang sử dụng hộp kiểm để chọn hai hoặc nhiều sản phẩm để cho phép người dùng so sánh thông số sản phẩm trên trang web mới bằng JSF 2.0. Tôi đã mất nhiều thời gian để tìm ra vấn đề sau (hoàn toàn hiển nhiên bây giờ) vì vậy nghĩ rằng nó đáng được đề cập đến cho những người đang cố gắng sử dụng mã số của BalusC ở trên (câu trả lời hay hơn BalusC, đơn giản hơn nhiều so với tôi tưởng tượng nó sẽ là).

Nếu bạn đang sử dụng pagination bạn sẽ nhận được nullpointers tại dòng:

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

-in đang BalusC của trên.

Điều này là do chỉ các hộp kiểm được hiển thị mới được thêm vào Bản đồ (doh; tát trán). Đối với những sản phẩm có hộp kiểm không bao giờ được hiển thị, do phân trang, dòng này sẽ dẫn đến lỗi con trỏ null và cần phải thêm dấu kiểm để bỏ qua các con trỏ rỗng này (giả sử rằng tất cả các hộp kiểm đều được bỏ chọn khi tải trang). Để người dùng đánh dấu vào một hộp kiểm, họ cần hiển thị trang phân trang để mọi thứ hoạt động tốt sau đó.

Nếu một số hoặc tất cả các hộp kiểm được yêu cầu phải được đánh dấu khi tải trang đầu tiên thì điều này sẽ không giúp ích gì cho bạn ...bạn sẽ phải thêm thủ công các bản đồ đó vào Bản đồ để chúng được hiển thị chính xác khi tải trang. Lưu ý: bởi vì tôi đang sử dụng đối tượng JPA 'Entity class from database' nên tôi cũng cần sử dụng @Transient cho id trong lớp ProductTbl Entity Class vì tất cả các biến được coi là các cột trong cơ sở dữ liệu bởi JPA, theo mặc định, trừ khi có tiền tố @Transient. Ngoài ra tôi đang sử dụng liên kết thứ hai để đặt lại các hộp kiểm, gọi clearSelections() và 'gửi' của tôi là liên kết gọi compareSelectedProducts() thay vì nút Gửi.

Mã đầy đủ như sau:

Trong lớp Entity 'ProductTbl' bắt nguồn từ cơ sở dữ liệu:

@Transient 
private Long id; 

public Long getId() 
{ 
    return id; 
} 

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

Trong đậu ủng hộ '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"; 
} 

Trong trang Web 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> 

Trong 'faces-config.xml' file:

<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> 
Các vấn đề liên quan