如何在 JSF 中创建有效的“全选”复选框

How to create effective "select all" checkbox in JSF

本文关键字:全选 复选框 有效 创建 JSF      更新时间:2023-09-26

我想在 JSF h:datatable 中实现全选复选框。这是代码,如果h:datatable

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"    
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
    <h:head>
        <ui:insert name="header">           
            <ui:include src="header.xhtml"/>         
        </ui:insert>
    </h:head>
    <h:body>
        <h1><img src="resources/css/images/icon.png" alt="DX-57" /> History Center</h1>
        <!-- layer for black background of the buttons -->
        <div id="toolbar" style="margin: 0 auto; width:1180px; height:30px; position:relative;  background-color:black">
            <!-- Include page Navigation -->
            <ui:insert name="Navigation">           
                <ui:include src="Navigation.xhtml"/>         
            </ui:insert>
        </div>  
        <div id="logodiv" style="position:relative; top:35px; left:0px;"> 
            <h:graphicImage alt="Dashboard"  style="position:relative; top:-20px; left:9px;"  value="resources/images/logo_sessions.png" />
        </div>
        <div id="main" style="margin: 0 auto; width:1190px; height:700px; position:absolute;  background-color:transparent; top:105px">
            <div id="mainpage" style="margin: 0 auto; width:1190px; height:500px; position:absolute;  background-color:transparent; top:80px">
                <div id="settingsHashMap" style="width:750px; height:400px; position:absolute;  background-color:r; top:20px; left:1px">
                    <h:form id="form">
                        <ui:debug />
                        <!-- The sortable data table -->
                        <h:dataTable id="dataTable" value="#{SessionsController.dataList}" binding="#{table}" var="item">
                            <!-- Check box -->
                            <h:column>
                                <f:facet name="header">
                                    <h:outputText value="Select" />
                                </f:facet>
                                <h:selectBooleanCheckbox onclick="highlight(this)" value="#{SessionsController.selectedIds[item.aSessionID]}" />
                            </h:column>
                            <h:column>
                                <f:facet name="header">
                                    <h:commandLink value="№" actionListener="#{SessionsController.sort}">
                                        <f:attribute name="№" value="№" />
                                    </h:commandLink>
                                </f:facet>
                                <h:outputText value="#{table.rowIndex + SessionsController.firstRow + 1}" />
                            </h:column>
                            <h:column>
                                <f:facet name="header">
                                    <h:commandLink value="Account Session ID" actionListener="#{SessionsController.sort}">
                                        <f:attribute name="sortField" value="Account Session ID" />
                                    </h:commandLink>
                                </f:facet>
                                <h:outputText value="#{item.aSessionID}" />
                            </h:column>
                            <h:column>
                                <f:facet name="header">
                                    <h:commandLink value="User ID" actionListener="#{SessionsController.sort}">
                                        <f:attribute name="sortField" value="User ID" />
                                    </h:commandLink>
                                </f:facet>
                                <h:outputText value="#{item.userID}" />
                            </h:column>
                            <h:column>
                                <f:facet name="header">
                                    <h:commandLink value="Activity Start Time" actionListener="#{SessionsController.sort}">
                                        <f:attribute name="sortField" value="Activity Start Time" />
                                    </h:commandLink>
                                </f:facet>
                                <h:outputText value="#{item.activityStart}" />
                            </h:column>
                            <h:column>
                                <f:facet name="header">
                                    <h:commandLink value="Activity End Time" actionListener="#{SessionsController.sort}">
                                        <f:attribute name="sortField" value="Activity End Time" />
                                    </h:commandLink>
                                </f:facet>
                                <h:outputText value="#{item.activityEnd}" />
                            </h:column>
                            <h:column>
                                <f:facet name="header">
                                    <h:commandLink value="Activity" actionListener="#{SessionsController.sort}">
                                        <f:attribute name="sortField" value="Activity" />
                                    </h:commandLink>
                                </f:facet>
                                <h:outputText value="#{item.activity}" />
                            </h:column>
                        </h:dataTable>
                        <!-- The paging buttons -->
                        <h:commandButton value="first" action="#{SessionsController.pageFirst}"
                                         disabled="#{SessionsController.firstRow == 0}" >
                            <f:ajax render="@form" execute="@form"></f:ajax>
                        </h:commandButton>

                        <h:commandButton value="prev" action="#{SessionsController.pagePrevious}"
                                         disabled="#{SessionsController.firstRow == 0}" >
                            <f:ajax render="@form" execute="@form"></f:ajax>
                        </h:commandButton>
                        <h:commandButton value="next" action="#{SessionsController.pageNext}"
                                         disabled="#{SessionsController.firstRow + SessionsController.rowsPerPage >= SessionsController.totalRows}" >
                            <f:ajax render="@form" execute="@form"></f:ajax>
                        </h:commandButton>    
                        <h:commandButton value="last" action="#{SessionsController.pageLast}"
                                         disabled="#{SessionsController.firstRow + SessionsController.rowsPerPage >= SessionsController.totalRows}" >
                            <f:ajax render="@form" execute="@form"></f:ajax>
                        </h:commandButton>
                        <h:outputText value="Page #{SessionsController.currentPage} / #{SessionsController.totalPages}" />
                        <br />
                        <!-- The paging links -->
                        <ui:repeat value="#{SessionsController.pages}" var="page">
                            <h:commandLink value="#{page}" actionListener="#{SessionsController.page}"
                                           rendered="#{page != SessionsController.currentPage}" >
                                <f:ajax render="@form" execute="@form"></f:ajax>   
                            </h:commandLink>
                            <h:outputText value="#{page}" escape="false"
                                          rendered="#{page == SessionsController.currentPage}" />
                        </ui:repeat>
                        <br />
                        <!-- Set rows per page -->
                        <h:outputLabel for="rowsPerPage" value="Rows per page" />
                        <h:inputText id="rowsPerPage" value="#{SessionsController.rowsPerPage}" size="3" maxlength="3" />
                        <h:commandButton value="Set" action="#{SessionsController.pageFirst}" >
                            <f:ajax render="@form" execute="@form"></f:ajax>
                        </h:commandButton>
                        <h:message for="rowsPerPage" errorStyle="color: red;" />
                        <h:commandButton value="Delete" action="#{SessionsController.deleteSelectedIDs}" >
                        </h:commandButton>
                    </h:form>                  
                </div>   
                <div id="settingsdivb" style="width:350px; height:400px; position:absolute;  background-color:transparent; top:20px; left:800px">
                </div>   
            </div>  
        </div>
    </h:body>
</html>

这是托管 Bean:

package com.DX_57.HM_57;
/*
 * include default packages for Beans
 */
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
// or import javax.faces.bean.SessionScoped;
import javax.inject.Named;
/*
 * include SQL Packages
 */
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import javax.annotation.Resource;
import javax.faces.bean.ViewScoped;
import javax.faces.component.UICommand;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
// or import javax.faces.bean.ManagedBean; 
import javax.faces.event.ActionEvent;
import org.glassfish.osgicdi.OSGiService;
@Named("SessionsController")
@ViewScoped
public class Sessions implements Serializable {
    /*
     * Call the Oracle JDBC Connection driver
     */
    @Resource(name = "jdbc/Oracle")
    private DataSource ds;
    // Data.
    private List<ActiveSessionObj> dataList;
    // Rows
    private int totalRows;
    // Paging.
    private int firstRow;
    private int rowsPerPage;
    private int totalPages;
    private int pageRange;
    private Integer[] pages;
    private int currentPage;
    // Sorting.
    private String sortField;
    private boolean sortAscending;
    /*
     * Constructor
     */
    public Sessions() {
        /*
         * Set default properties
         */
        rowsPerPage = 10; // Default rows per page (max amount of rows to be displayed at once).
        pageRange = 10; // Default page range (max amount of page links to be displayed at once).
        sortField = "ASESSIONID"; // Default sort field.
        sortAscending = true; // Default sort direction.
    }
    public class ActiveSessionObj {
        /*
         * Oracle table structure CREATE TABLE ACTIVESESSIONSLOG( ASESSIONID
         * VARCHAR2(30 ) NOT NULL, USERID VARCHAR2(30 ), ACTIVITYSTART
         * TIMESTAMP(6), ACTIVITYEND TIMESTAMP(6), ACTIVITY CLOB )
         */
        private String aSessionID;
        private String userID;
        private Date activityStart;
        private Date activityEnd;
        private String activity;
        //private boolean selected;
        public ActiveSessionObj(String aSessionID, String userID, Date activityStart, Date activityEnd, String activity) {
            this.aSessionID = aSessionID;
            this.userID = userID;
            this.activityStart = activityStart;
            this.activityEnd = activityEnd;
            this.activity = activity;
        }
        public int getFirstRow() {
            return firstRow;
        }
        public String getaSessionID() {
            return aSessionID;
        }
        public void setaSessionID(String aSessionID) {
            this.aSessionID = aSessionID;
        }
        public String getactivity() {
            return activity;
        }
        public void setactivity(String activity) {
            this.activity = activity;
        }
        public Date getactivityEnd() {
            return activityEnd;
        }
        public void setactivityEnd(Date activityEnd) {
            this.activityEnd = activityEnd;
        }
        public Date getactivityStart() {
            return activityStart;
        }
        public void setactivityStart(Date activityStart) {
            this.activityStart = activityStart;
        }
        public String getuserID() {
            return userID;
        }
        public void setuserID(String userID) {
            this.userID = userID;
        }
        private ActiveSessionObj() {
            throw new UnsupportedOperationException("Not yet implemented");
        }
    }
    // Paging actions -----------------------------------------------------------------------------
    public void pageFirst() {
        page(0);
    }
    public void pageNext() {
        page(firstRow + rowsPerPage);
    }
    public void pagePrevious() {
        page(firstRow - rowsPerPage);
    }
    public void pageLast() {
        page(totalRows - ((totalRows % rowsPerPage != 0) ? totalRows % rowsPerPage : rowsPerPage));
    }
    public void page(ActionEvent event) {
        page(((Integer) ((UICommand) event.getComponent()).getValue() - 1) * rowsPerPage);
    }
    private void page(int firstRow) {
        this.firstRow = firstRow;
        loadDataList(); // Load requested page.
    }
    // Sorting actions ----------------------------------------------------------------------------
    public void sort(ActionEvent event) {
        String sortFieldAttribute = (String) event.getComponent().getAttributes().get("sortField");
        // If the same field is sorted, then reverse order, else sort the new field ascending.
        if (sortField.equals(sortFieldAttribute)) {
            sortAscending = !sortAscending;
        } else {
            sortField = sortFieldAttribute;
            sortAscending = true;
        }
        pageFirst(); // Go to first page and load requested page.
    }
    // Loaders ------------------------------------------------------------------------------------
    private void loadDataList() {
        // Load list and totalCount.
        try {
            dataList = list(firstRow, rowsPerPage, sortField, sortAscending);
            totalRows = countDBRowNum(); //count the tablerows
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        // Set currentPage, totalPages and pages.
        currentPage = (totalRows / rowsPerPage) - ((totalRows - firstRow) / rowsPerPage) + 1;
        totalPages = (totalRows / rowsPerPage) + ((totalRows % rowsPerPage != 0) ? 1 : 0);
        int pagesLength = Math.min(pageRange, totalPages);
        pages = new Integer[pagesLength];
        // firstPage must be greater than 0 and lesser than totalPages-pageLength.
        int firstPage = Math.min(Math.max(0, currentPage - (pageRange / 2)), totalPages - pagesLength);
        // Create pages (page numbers for page links).
        for (int i = 0; i < pagesLength; i++) {
            pages[i] = ++firstPage;
        }
    }
    // Getters ------------------------------------------------------------------------------------
    public List<ActiveSessionObj> getdataList() {
        if (dataList == null) {
            loadDataList(); // Preload page for the 1st view.
        }
        return dataList;
    }
    public int getTotalRows() {
        return totalRows;
    }
    public int getFirstRow() {
        return firstRow;
    }
    public int getRowsPerPage() {
        return rowsPerPage;
    }
    public Integer[] getPages() {
        return pages;
    }
    public int getCurrentPage() {
        return currentPage;
    }
    public int getTotalPages() {
        return totalPages;
    }
    // Setters ------------------------------------------------------------------------------------
    public void setRowsPerPage(int rowsPerPage) {
        this.rowsPerPage = rowsPerPage;
    }
    // Actions ------------------------------------------------------------------------------------
    /**
     * Returns list of ActiveSessionObj items starting at the given first index
     * with the given row count, sorted by the given sort field and sort order.
     *
     * @param firstRow First index of rows to be returned.
     * @param rowCount Amount of rows to be returned.
     * @param sortField Field to sort the data on.
     * @param sortAscending Whether to sort data ascending or not.
     * @return list of ActiveSessionObj items starting at the given first index
     * with the given row count, sorted by the given sort field and sort order.
     * @throws DAOException If something fails at DAO level.
     */
    public List<ActiveSessionObj> list(int firstRow, int rowCount, String sortField, boolean sortAscending) throws SQLException {
        String SqlStatementSmall = null;
        String SQLStatementLarge = null;
        if (ds == null) {
            throw new SQLException();
        }
        Connection conn = ds.getConnection();
        if (conn == null) {
            throw new SQLException();
        }
        int countrow = firstRow + rowCount;
        String sortDirection = sortAscending ? "ASC" : "DESC";
        /*
         * For small tables
         */
        SqlStatementSmall = "SELECT c.*"
                + " FROM (SELECT b.*, rownum rn"
                + " FROM (SELECT a.*"
                + " FROM activeSessionsLog a"
                + " ORDER BY %s %s) b"
                + " WHERE rownum <= ?) c"
                + " WHERE rn > ?";
        /*
         * For huge datatables optimized for perfomance
         */
        SQLStatementLarge = "select * from"
                + " (select asl.*, row_number() over (order by userid asc) r "
                + " from activesessionslog asl)"
                + " where r > 980750 and r <= 980800;";

        String sql = String.format(SqlStatementSmall, sortField, sortDirection);
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        List<ActiveSessionObj> dataList = new ArrayList<ActiveSessionObj>();
        try {
            conn.setAutoCommit(false);
            boolean committed = false;
            ps = conn.prepareStatement(sql);
            ps.setInt(1, countrow);
            ps.setInt(2, firstRow);

            resultSet = ps.executeQuery();
            /*
             * take the result from the SQL query and insert it into Array List
             * collection
             */
            dataList = ActiveSessionsArrayList(resultSet);
            conn.commit();
            committed = true;

        } finally {
            ps.close();
            conn.close();
        }
        return dataList;
    }
    /**
     * Returns total amount of rows in table.
     *
     * @return Total amount of rows in table.
     * @throws DAOException If something fails at DAO level.
     */
    public int countDBRowNum() throws Exception {
        String SqlStatement = null;
        if (ds == null) {
            throw new SQLException();
        }
        Connection conn = ds.getConnection();
        if (conn == null) {
            throw new SQLException();
        }
        SqlStatement = "SELECT count(*) FROM ACTIVESESSIONSLOG";
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        int count = 0;
        try {
            conn.setAutoCommit(false);
            boolean committed = false;
            try {
                SqlStatement = "SELECT count(*) FROM ACTIVESESSIONSLOG";
                ps = conn.prepareStatement(SqlStatement);
                resultSet = ps.executeQuery();
                if (resultSet.next()) {
                    count = resultSet.getInt(1);
                }
                conn.commit();
                committed = true;
            } finally {
                if (!committed) {
                    conn.rollback();
                }
            }
        } finally {
            ps.close();
            conn.close();
        }
        return count;
    }
    /**
     * Map the current row of the given ResultSet to ActiveSessionObj.
     *
     * @param resultSet The ResultSet of which the current row is to be mapped
     * to ActiveSessionObj.
     * @return The mapped ActiveSessionObj from the current row of the given
     * ResultSet.
     * @throws SQLException If something fails at database level.
     */
    private ArrayList<ActiveSessionObj> ActiveSessionsArrayList(ResultSet rs) throws SQLException {
        ArrayList<ActiveSessionObj> list = new ArrayList<>();

        try {
            while (rs.next()) {
                list.add(new ActiveSessionObj(
                        rs.getString("ASESSIONID"),
                        rs.getString("USERID"),
                        timestampToDate(rs.getTimestamp("ACTIVITYSTART")),
                        timestampToDate(rs.getTimestamp("ACTIVITYEND")),
                        rs.getString("ACTIVITY")));
            }
        } catch (Exception x) {
            x.printStackTrace();
        }
        return list;   
    }
    //get the selected rows
    private HashMap<String, Boolean> selectedIds = new HashMap<>();
    // get the list from the JSF page
    public Map<String, Boolean> getSelectedIds() {
        return selectedIds;
    }
    //delete all selected checkboxes
    public void deleteSelectedIDs() throws SQLException {
        boolean success = false;
        if (ds == null) {
            throw new SQLException();
        }
        Connection conn = ds.getConnection();
        if (conn == null) {
            throw new SQLException();
        }
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        try {
            conn.setAutoCommit(false);
            boolean committed = false;
            try {
                String sqlDeleteQuery = "DELETE FROM ACTIVESESSIONSLOG WHERE ASESSIONID = ?";

                Set<String> keySet = selectedIds.keySet();
                String[] keys = new String[]{};
                keys = selectedIds.keySet().toArray(keys);
                ps = conn.prepareStatement(sqlDeleteQuery);
                for (int i = 0; i < keys.length; i++) {
                    ps.setString(1, keys[i]);
                    ps.executeUpdate();
                    ps.clearParameters();
                    selectedIds.put(keys[i], false); //get(keys[i]) = false;
                }
                conn.commit();
                committed = true;
                //selectedIds.clear();
            } finally {
                if (!committed) {
                    conn.rollback();
                }
            }
        } finally {
            ps.close();
            conn.close();
        }
        /*
         * // Get selected items. boolean success = false; try { String
         * sqlDeleteQuery = "";
         *
         * Set<String> keySet = selectedIds.keySet(); Iterator keyIterator =
         * keySet.iterator(); while(keyIterator.hasNext()) { keyIterator.next();
         * }
         *
         * }
         * catch(Exception x) { success = false; } // Do your thing with the
         * MyData items in List selectedDataList.
         */
        //return success; // Navigation case.
    }

    private static Date timestampToDate(java.sql.Timestamp ts) {
        Date d = null;
        try {
            d = new Date(ts.getTime());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return d;
    }
}

我的问题是如何实现选修select all按钮。一种创建java方法的方法,该方法获取数据库表的所有键并创建存储所有键的哈希图。像这样:

private HashMap<String, Boolean> selectedIds = new HashMap<>();

当我尝试实现选择行复选框时,此代码非常有效。问题是,当我有一百万行或更多行进入数据库表时会发生什么?在这种情况下,所有键都将插入到一个非常大的哈希图中,也许我会因为内存消耗太大而出错。有没有更优化的解决方案?

愿你安好彼得

更新

我已经实现了简单的复选框,用于选择行并传递它们以删除java方法,该方法使用key将行删除到数据库表中。但是我如何在 JavaScript 客户端实现select all并调用从数据库表中删除所有记录的 java 方法呢?

你可以做这样的事情

<h:column id="selection_column">
    <f:facet name="header">
         <h:selectBooleanCheckbox class="checkall"/>
    </f:facet>
    <h:selectBooleanCheckbox value="#{SessionsController.selectedIds[item.aSessionID]}" />
</h:column>

在你的 js 中输入此代码

    $(window).load(function () {
        $(document).delegate(".checkall", "click", function(event) {
              $(this).closest("table").find(':checkbox').attr('checked', this.checked);
        });
    });

b.t.w 而不是存储在 map 中,您可以像这样将属性添加到迭代item:而不是value="#{SessionsController.selectedIds[item.aSessionID]}"这样的东西value="#{item.selected}"

稍后您可以在服务器端迭代它们并添加到将发送给您的列表中 删除方法...

选择是客户端操作。所以你可以使用 JavaScript 来实现这一点。一个想法是将特定的CSS类添加到要选择的所有复选框中(然后将它们全部选中会更容易(:

<h:column>
    <f:facet name="header">
        <h:outputText value="Select" />
    </f:facet>
    <h:selectBooleanCheckbox styleClass="selectable-checkbox" onclick="highlight(this)" value="#{SessionsController.selectedIds[item.aSessionID]}" />
</h:column>

然后,您可以简单地使用以下 jQuery 代码来检查具有此特定 CSS 类的所有元素:jQuery(".selectable-checkbox").attr("checked", true);

如果你没有使用jQuery,你可以做同样的事情,稍微调整一下这里显示的代码:如何在JavaScript中按类获取元素?


关于您的编辑:

您想要一个按钮Select all删除表中的所有项目吗?

如果需要实现此目的,请将此按钮重命名为仅调用 Java 方法(即经典<h:commandButton><h:commandLink>(的Delete all items,而无需选中复选框。选择项目有什么兴趣,因为您将在那之后删除它们?

对于 JSF 2 ,对于选择模式中数据表中的选定所有行,分页器=true 的倍数:在页面中

<p:dataTable widgetVar="tableArea" yourtags...>
   <p:ajax  event="toggleSelect" oncomplete="teste()" /> /// toggleSelect is dispared on click to checkbox header
<p:column id="columnId" selectionMode="multiple"/>

在 js 中:

function teste(){    		
	var checked = $(document).find(":checkbox")["0"].checked; ///Find checkbox header and verify if checkbox is checked
	if(checked == true){
		PF('tableArea').selectAllRows(); // if true, selectAllRows from datatable
	} else {
		PF('tableArea').unselectAllRows(); //
	}		
}

我使用此代码选择"全部"复选框:

$(window(.load(function (( {

    $(document).delegate(".checkall", "click", function(event) {
          $(this).closest("table").find(':checkbox').attr('checked', this.checked);
    });
});

当我在标题中选择/取消选择复选框时,它工作正常,然后选中/取消选择该列下的所有复选框。但是,如果我再次选择相同的复选框,则不会选中其他复选框。.