JSF資料表(h:dataTable)DataModel排序資料


JSF中有一個叫作DataTable的控制元件,可用來渲染和格式化html表格。使用DataTable,我們可以疊代收集或陣列陣列來顯示資料。下面我們來學習如何向DataTable使用DataModel排序資料。

要使用DataTable,我們需要新增以下HTML頭。

<html 
   xmlns="http://www.w3.org/1999/xhtml"   
   xmlns:h="http://java.sun.com/jsf/html">
</html>

以下JSF標籤 -

<h:dataTable value="#{userData.employees}" var="employee"
   styleClass="employeeTable"
   headerClass="employeeTableHeader"
   rowClasses="employeeTableOddRow,employeeTableEvenRow">
   <h:column>            
      <f:facet name="header">Name</f:facet>            
      #{employee.name}
   </h:column>
   <h:column>
      <f:facet name="header">Department</f:facet>
      #{employee.department}
   </h:column>
   <h:column>
      <f:facet name="header">Age</f:facet>
      #{employee.age}
   </h:column>
   <h:column>
      <f:facet name="header">Salary</f:facet>
      #{employee.salary}
   </h:column>
</h:dataTable>

被渲染成以下HTML標籤。

<table class="employeeTable">
<thead><tr>
   <th class="employeeTableHeader" scope="col">Name</th>
   <th class="employeeTableHeader" scope="col">Department</th>
   <th class="employeeTableHeader" scope="col">Age</th>
   <th class="employeeTableHeader" scope="col">Salary</th>
</tr></thead>
<tbody>
<tr class="employeeTableOddRow">
   <td>Tom</td>
   <td>Marketing</td>
   <td>10</td>
   <td>2000.0</td>
</tr>
<tr class="employeeTableEvenRow">
   <td>Robert</td>
   <td>Marketing</td>
   <td>15</td>
   <td>1000.0</td>
</tr>
</table>

JSF資料表更新行資料範例

開啟 NetBeans IDE 建立一個Web工程:DataTableSortDataModel,其目錄結構如下所示 -

建立以下檔案程式碼,檔案:index.xhtml 的程式碼內容如下所示 -

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"   
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:c="http://java.sun.com/jsp/jstl/core"
      >
    <h:head>
        <h:outputStylesheet library="css" name="table-style.css"  />
    </h:head>
    <h:body>

        <h1>JSF 2 dataTable sorting example</h1>
        <h:form>
            <h:dataTable value="#{book.bookList}" var="o"
                         styleClass="book-table"
                         headerClass="book-table-header"
                         rowClasses="book-table-odd-row,book-table-even-row">
                <h:column>
                    <f:facet name="header">
                        <h:commandLink action="#{book.sortByBookNo}">
                            Book No
                        </h:commandLink>
                    </f:facet>
                    #{o.bookNo}
                </h:column>

                <h:column>
                    <f:facet name="header">
                        Product Name
                    </f:facet>
                    #{o.productName}
                </h:column>

                <h:column>
                    <f:facet name="header">Price</f:facet>
                        #{o.price}
                </h:column>

                <h:column>
                    <f:facet name="header">Quantity</f:facet>
                        #{o.qty}
                </h:column>

            </h:dataTable>
        </h:form>

    </h:body>
</html>

檔案:User.java 的程式碼內容如下所示 -

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.yiibai;

/**
 *
 * @author Maxsu
 */
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Comparator;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.model.ArrayDataModel;
import javax.faces.model.DataModel;
import java.util.Arrays;
import java.util.Comparator;
import javax.faces.model.DataModel;

@ManagedBean(name = "book")
@SessionScoped
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    private SortableDataModel<Book> sotableDataModel;

    private boolean sortAscending = true;

    private static final Book[] bookList = {
        new Book("1", "CSS", new BigDecimal("1500.00"), 3),
        new Book("2", "HTML", new BigDecimal("421.00"), 6),
        new Book("3", "Java", new BigDecimal("5222.00"), 10),
        new Book("4", "Javascript", new BigDecimal("1111.00"), 9),
        new Book("5", "SQL", new BigDecimal("211.00"), 20)
    };

    public User() {
        sotableDataModel = new SortableDataModel<Book>(new ArrayDataModel<Book>(bookList));

    }

    public DataModel<Book> getBookList() {

        return sotableDataModel;

    }

    //sort by book no
    public String sortByBookNo() {
        if (sortAscending) {
            sotableDataModel.sortBy(new Comparator<Book>() {
                @Override
                public int compare(Book o1, Book o2) {
                    return o1.getBookNo().compareTo(o2.getBookNo());
                }
            });
            sortAscending = false;
        } else {
            //descending book
            sotableDataModel.sortBy(new Comparator<Book>() {
                @Override
                public int compare(Book o1, Book o2) {
                    return o2.getBookNo().compareTo(o1.getBookNo());
                }
            });
            sortAscending = true;
        }
        return null;
    }

    public static class Book {

        String bookNo;
        String productName;
        BigDecimal price;
        int qty;

        public Book(String bookNo, String productName,
                BigDecimal price, int qty) {
            this.bookNo = bookNo;
            this.productName = productName;
            this.price = price;
            this.qty = qty;
        }

        public String getBookNo() {
            return bookNo;
        }

        public void setBookNo(String bookNo) {
            this.bookNo = bookNo;
        }

        public String getProductName() {
            return productName;
        }

        public void setProductName(String productName) {
            this.productName = productName;
        }

        public BigDecimal getPrice() {
            return price;
        }

        public void setPrice(BigDecimal price) {
            this.price = price;
        }

        public int getQty() {
            return qty;
        }

        public void setQty(int qty) {
            this.qty = qty;
        }

    }
}

class SortableDataModel<E> extends DataModel<E> {

    DataModel<E> model;
    private Integer[] rows;

    SortableDataModel(DataModel<E> model) {
        this.model = model;
        initRows();
    }

    public void initRows() {
        int rowCount = model.getRowCount();
        if (rowCount != -1) {
            this.rows = new Integer[rowCount];
            for (int i = 0; i < rowCount; ++i) {
                rows[i] = i;
            }
        }
    }

    public void sortBy(final Comparator<E> comparator) {
        Comparator<Integer> rowComp = new Comparator<Integer>() {
            public int compare(Integer i1, Integer i2) {
                E o1 = getData(i1);
                E o2 = getData(i2);
                return comparator.compare(o1, o2);
            }
        };
        Arrays.sort(rows, rowComp);

    }

    private E getData(int row) {
        int originalRowIndex = model.getRowIndex();

        model.setRowIndex(row);
        E newRowData = model.getRowData();
        model.setRowIndex(originalRowIndex);

        return newRowData;
    }

    @Override
    public void setRowIndex(int rowIndex) {

        if (0 <= rowIndex && rowIndex < rows.length) {
            model.setRowIndex(rows[rowIndex]);
        } else {
            model.setRowIndex(rowIndex);
        }
    }

    @Override
    public boolean isRowAvailable() {
        return model.isRowAvailable();
    }

    @Override
    public int getRowCount() {
        return model.getRowCount();
    }

    @Override
    public E getRowData() {
        return model.getRowData();
    }

    @Override
    public int getRowIndex() {
        return model.getRowIndex();
    }

    @Override
    public Object getWrappedData() {
        return model.getWrappedData();
    }

    @Override
    public void setWrappedData(Object data) {

        model.setWrappedData(data);
        initRows();
    }
}

檔案:table-style.css 的程式碼內容如下所示 -

.book-table-header{
  bbook-bottom:1px solid #BBB;
  padding:16px;
}

.book-table-odd-row{
  bbook-top:1px solid #BBB;
}

.book-table-even-row{
  bbook-top:1px solid #BBB;
}

右鍵執行工程:DataTableSortDataModel,如果沒有任何錯誤,開啟瀏覽器存取:

http://localhost:8084/DataTableSortDataModel/

應該會看到以下結果 -

在上圖中,您可以點選」Book No「,就可以看到排序情況了。