- 浏览: 77605 次
- 来自: ...
最新评论
-
Linuxboy:
配置介绍原文:https://fedoraproject.or ...
xorg-server禁用hal的配置方法[from Fedora] -
Linuxboy:
网上有很多关于mysql,hibernate,proxool等 ...
T5学习小结之五(tapestry-hibernate的基本应用) -
lucumu:
请问,数据库怎么配置阿
T5学习小结之五(tapestry-hibernate的基本应用) -
Linuxboy:
最新版本的mplayer已经支持ASS了。
gnome-mplayer:轻盈小巧的mplayer前端 -
Linuxboy:
sun58224 写道RequestGlobals, requ ...
Tapestry5学习小结之六(CJK解决方案)
T5版本:tapestry-5.2.4
自定义PagedLoop组件的目的:
- 最主要的目的是对数据源进行分页。目前已公布的分页组件实现有两个,一个是chenillekit的PagedLoop, 一个是equanda版的JSPagedLoop。两者的区别是后者使用了ajax。
- 翻页时只从数据库中读取当前页的数据记录,而不是全部记录。
- 可以对读取的数据进行降序排列。
一、 源代码
PagedLoop.java
package org.example.components; import java.util.Iterator; import org.apache.tapestry5.Block; import org.apache.tapestry5.ClientElement; import org.apache.tapestry5.ValueEncoder; import org.apache.tapestry5.annotations.Component; import org.apache.tapestry5.annotations.Parameter; import org.apache.tapestry5.annotations.Persist; import org.apache.tapestry5.corelib.components.Delegate; import org.apache.tapestry5.corelib.components.Loop; import org.apache.tapestry5.corelib.data.GridPagerPosition; import org.apache.tapestry5.util.StringToEnumCoercion; import org.northstar.worklive.internal.LoopDataSource; public class PagedLoop implements ClientElement { //@Parameter(value = "prop:componentResources.id", defaultPrefix = "literal") //private String clientId; /** * The element to render. If not null, then the loop will render the * indicated element around its body (on each pass through the loop). The * default is derived from the component template. */ @Parameter(value = "prop:componentResources.elementName", defaultPrefix = "literal") private String elementName; /** * The element to render. If not null, then the loop will render the * indicated element around its body (on each pass through the loop). The * default is derived from the component template. */ @Parameter(required = true, principal = true, autoconnect = true) private LoopDataSource source; /** * A wrapper around the provided Data Source that caches access to the * availableRows property. This is the source provided to sub-components. */ private LoopDataSource cachingSource; /** * Defines where the pager (used to navigate within the "pages" of results) * should be displayed: "top", "bottom", "both" or "none". */ @Parameter(value = "bottom", defaultPrefix = "literal" ) private String pagerPosition; private GridPagerPosition internalPagerPosition; /** * The number of rows of data displayed on each page. If there are more rows * than will fit, the Grid will divide up the rows into "pages" and * (normally) provide a pager to allow the user to navigate within the * overall result set. */ @Parameter("25") private int rowsPerPage; @Persist private int currentPage; /** * The current value, set before the component renders its body. */ @SuppressWarnings("unused") @Parameter private Object value; /** *If true and the Loop is enclosed by a Form, then the normal state saving logic is turned off. * Defaults to false, enabling state saving logic within Forms. */ @SuppressWarnings("unused") @Parameter(name = "volatile") private boolean volatileState; /** * The index into the source items. */ @SuppressWarnings("unused") @Parameter private int index; /** * Optional primary key converter; if provided and inside a form and not * volatile, then each iterated value is converted and stored into the form. */ @SuppressWarnings("unused") @Parameter private ValueEncoder<?> encoder; @SuppressWarnings("unused") @Component(parameters = { "source=dataSource", "elementName=prop:elementName", "value=inherit:value", "volatile=inherit:volatileState", "encoder=inherit:encoder", "index=inherit:index" }) private Loop loop; @Component(parameters = { "source=dataSource", "rowsPerPage=rowsPerPage", "currentPage=currentPage" }) private Pager pager; @SuppressWarnings("unused") @Component(parameters = "to=pagerTop") private Delegate pagerTop; @SuppressWarnings("unused") @Component(parameters = "to=pagerBottom") private Delegate pagerBottom; /** * A Block to render instead of the table (and pager, etc.) when the source * is empty. The default is simply the text "There is no data to display". * This parameter is used to customize that message, possibly including * components to allow the user to create new objects. */ @Parameter(value = "block:empty") private Block empty; private String assignedClientId; @Parameter(name="OrderBy", defaultPrefix = "literal") private String propertyName; /** * A version of LoopDataSource that caches the availableRows property. This addresses TAPESTRY-2245. */ static class CachingDataSource implements LoopDataSource { private final LoopDataSource delegate; private boolean availableRowsCached; private int availableRows; CachingDataSource(LoopDataSource delegate) { this.delegate = delegate; } public int getTotalRowCount() { if (!availableRowsCached) { availableRows = delegate.getTotalRowCount(); availableRowsCached = true; } return availableRows; } public void prepare(int startIndex, int endIndex, String propertyName) { delegate.prepare(startIndex, endIndex, propertyName); } /*public Object getRowValue(int index) { return delegate.getRowValue(index); } public Class<?> getRowType() { return delegate.getRowType(); }*/ @Override public Iterator<Object> iterator() { return delegate.iterator(); } } public String getElementName() { return elementName; } public Object getPagerTop() { return internalPagerPosition.isMatchTop() ? pager : null; } public Object getPagerBottom() { return internalPagerPosition.isMatchBottom() ? pager : null; } public int getRowsPerPage() { return rowsPerPage; } public void setRowsPerPage(int rowsPerPage) { this.rowsPerPage = rowsPerPage; } public int getCurrentPage() { return currentPage; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } void setupDataSource() { cachingSource = new CachingDataSource(source); int availableRows = cachingSource.getTotalRowCount(); if (availableRows == 0) return; int maxPage = ((availableRows - 1) / rowsPerPage) + 1; // This captures when the number of rows has decreased, typically due to deletions. int effectiveCurrentPage = getCurrentPage(); if (effectiveCurrentPage > maxPage) effectiveCurrentPage = maxPage; int startIndex = (effectiveCurrentPage - 1) * rowsPerPage; int endIndex = Math.min(startIndex + rowsPerPage - 1, availableRows - 1); cachingSource.prepare(startIndex, endIndex, propertyName); } Object setupRender() { if (currentPage == 0) currentPage = 1; internalPagerPosition = new StringToEnumCoercion<GridPagerPosition>( GridPagerPosition.class).coerce(pagerPosition); setupDataSource(); // If there's no rows, display the empty block placeholder. return cachingSource.getTotalRowCount() == 0 ? empty : null; } Object beginRender() { // Skip rendering of component (template, body, etc.) when there's // nothing to display. // The empty placeholder will already have rendered. return (cachingSource.getTotalRowCount() != 0); } void onAction(int newPage){ currentPage = newPage; } /** * Returns a unique id for the element. This value will be unique for any given rendering of a * page. This value is intended for use as the id attribute of the client-side element, and will * be used with any DHTML/Ajax related JavaScript. */ @Override public String getClientId() { return assignedClientId; } public LoopDataSource getDataSource(){ return cachingSource; } public String getPropertyName(){ return propertyName; } public void setPropertyName(String name){ propertyName = name; } }
PagedLoop.tml
<t:container xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd"> <div t:id="pagerTop"/> <t:loop t:id="loop"><t:body/></t:loop> <div t:id="pagerBottom"/> <t:block> <div t:id="pager"/> </t:block> <t:block id="empty">${message:empty.list}</t:block> </t:container>
Pager.java(是复制GridPager.java过来的,只不过修改了source参数的数据类型)
package org.example.components; import org.apache.tapestry5.*; import org.apache.tapestry5.annotations.Environmental; import org.apache.tapestry5.annotations.Events; import org.apache.tapestry5.annotations.Parameter; import org.apache.tapestry5.dom.Element; import org.apache.tapestry5.grid.GridDataSource; import org.apache.tapestry5.internal.InternalConstants; import org.apache.tapestry5.ioc.Messages; import org.apache.tapestry5.ioc.annotations.Inject; import org.apache.tapestry5.services.ClientBehaviorSupport; import org.apache.tapestry5.services.javascript.JavaScriptSupport; import org.northstar.worklive.internal.LoopDataSource; /** * Generates a series of links used to jump to a particular page index within the overall data set. */ @Events(InternalConstants.GRID_INPLACE_UPDATE + " (internal event)") public class Pager { /** * The source of the data displayed by the grid (this is used to determine {@link GridDataSource#getAvailableRows() * how many rows are available}, which in turn determines the page count). */ @Parameter(required = true) private LoopDataSource source; /** * The number of rows displayed per page. */ @Parameter(required = true) private int rowsPerPage; /** * The current page number (indexed from 1). */ @Parameter(required = true) private int currentPage; /** * Number of pages before and after the current page in the range. The pager always displays links for 2 * range + 1 * pages, unless that's more than the total number of available pages. */ @Parameter("5") private int range; /** * If not null, then each link is output as a link to update the specified zone. */ @Parameter private String zone; private int lastIndex; private int maxPages; @Inject private ComponentResources resources; @Inject private Messages messages; @Environmental private ClientBehaviorSupport clientBehaviorSupport; @Environmental private JavaScriptSupport jsSupport; void beginRender(MarkupWriter writer) { int availableRows = source.getTotalRowCount(); maxPages = ((availableRows - 1) / rowsPerPage) + 1; if (maxPages < 2) return; writer.element("div", "class", "t-data-grid-pager"); lastIndex = 0; for (int i = 1; i <= 2; i++) writePageLink(writer, i); int low = currentPage - range; int high = currentPage + range; if (low < 1) { low = 1; high = 2 * range + 1; } else { if (high > maxPages) { high = maxPages; low = high - 2 * range; } } for (int i = low; i <= high; i++) writePageLink(writer, i); for (int i = maxPages - 1; i <= maxPages; i++) writePageLink(writer, i); writer.end(); } private void writePageLink(MarkupWriter writer, int pageIndex) { if (pageIndex < 1 || pageIndex > maxPages) return; if (pageIndex <= lastIndex) return; if (pageIndex != lastIndex + 1) writer.write(" ... "); lastIndex = pageIndex; if (pageIndex == currentPage) { writer.element("span", "class", "current"); writer.write(Integer.toString(pageIndex)); writer.end(); return; } Object[] context = zone == null ? new Object[] { pageIndex } : new Object[] { pageIndex, zone }; Link link = resources.createEventLink(EventConstants.ACTION, context); Element element = writer.element("a", "href", zone == null ? link : "#", "title", messages.format("goto-page", pageIndex)); writer.write(Integer.toString(pageIndex)); writer.end(); if (zone != null) { String id = jsSupport.allocateClientId(resources); element.attribute("id", id); clientBehaviorSupport.linkZone(id, zone, link); } } /** * Normal, non-Ajax event handler. */ void onAction(int newPage) { // TODO: Validate newPage in range currentPage = newPage; } /** * Akjax event handler, passing the zone along. */ boolean onAction(int newPage, String zone) { onAction(newPage); resources.triggerEvent(InternalConstants.GRID_INPLACE_UPDATE, new Object[] { zone }, null); return true; // abort event } }
数据源接口:LoopDataSource.java
package org.example.internal; public interface LoopDataSource extends Iterable<Object>{ int getTotalRowCount(); void prepare(int startIndex, int endIndex, String propertyName); //Object getRowValue(int index); //Class<?> getRowType(); }
数据源接口实现:HibernateLoopDataSource.java
package org.example.internal; import java.util.Iterator; import java.util.List; import org.hibernate.Criteria; import org.hibernate.Session; import org.hibernate.criterion.Order; import org.hibernate.criterion.Projections; public class HibernateLoopDataSource implements LoopDataSource { private final Session session; private final Class<?> entityType; //private int startIndex; private List<Object> preparedResults; public HibernateLoopDataSource(Session session, Class<?> entityType){ assert session != null; assert entityType != null; this.session = session; this.entityType = entityType; } public int getTotalRowCount(){ Criteria criteria = session.createCriteria(entityType); criteria.setProjection(Projections.rowCount()); Number result = (Number) criteria.uniqueResult(); return result.intValue(); } @SuppressWarnings("unchecked") public void prepare(int startIndex, int endIndex, String propertyName){ Criteria crit = session.createCriteria(entityType); crit.setFirstResult(startIndex).setMaxResults(endIndex - startIndex + 1); if(propertyName!=null){ crit.addOrder(Order.desc(propertyName));} //this.startIndex = startIndex; preparedResults = crit.list(); } /*public Object getRowValue(int index) { return preparedResults.get(index - startIndex); } *//** * Returns the entity type, as provided via the constructor. *//* public Class<?> getRowType() { return entityType; } */ @Override public Iterator<Object> iterator() { return preparedResults.iterator(); } }
二、应用
<t:pagedLoop source="blogs" rowsperpage="10" value="blog"/>
@Inject private Session session; //Hibernate session @Property private Blog blog; //Entity public LoopDataSource getBlogs(){ return new HibernateLoopDataSource(session, Blog.class); }
发表评论
-
sitebricks 学习笔记之用户登录和ajax form
2012-08-21 09:48 1897这次是一个简单的登录界面,前台由jquery.form负责判断 ... -
sitebricks 学习笔记之分页widget(@Pager)
2012-08-15 17:46 1192UPDATE:重新优化了一下代码,减少一次页面请求读取数据库的 ... -
sitebricks 学习笔记之guice-persist的配置和使用
2012-08-13 12:04 1952目前能够通过简单的配置就可以使用的guice 模块,我所知的是 ... -
sitebricks 学习笔记之Decoration
2012-08-13 11:04 1118sitebricks 的 decoration是类似于apac ... -
转载:Tapestry5: Caching Method Results
2010-12-29 01:47 1071Tapestry5: Caching Method Res ... -
Tapestry5之日期格式化:Output 组件的使用
2010-12-27 17:47 1228以前一直自己用代码来格式化日期,现在(可能T5在很久以前就已经 ... -
tapestry-5.2.4中context values和request parameters应用
2010-12-25 22:57 1496一、context values tapestry默认使用的 ... -
[Tapestry5.0.6]DateFieldDemo
2007-12-05 18:26 1391DateFieldDemo.tml <html xm ... -
Tapestry5学习小结之六(CJK解决方案)
2007-04-17 20:57 3830转自mail-lists Nick Westgate ... -
T5学习小结之五(tapestry-hibernate的基本应用)
2007-04-05 15:14 4975环境: 1.容器:tomcat-6.0.10 2.Tapest ... -
T5学习小结之四(Form的基本应用2)
2007-03-06 12:46 2688同样是简单的login流程,下面展示如何进行page navi ... -
Tapestry5学习之三(转载:Select的用法)
2007-02-28 10:57 2540本文转自:http://bclxz520.iteye.com/ ... -
Tapestry5学习小结之二(Loop&ActionLink的基本应用)
2007-02-25 17:19 5791Start.html <html xml ... -
T5学习小结(Form的基本应用)
2007-02-22 00:00 2901一个简单的Login流程:Login.html -> S ... -
正在Tapestry和Wicket之间徘徊(一)
2006-12-12 10:05 2700我最早接触的Web框架是struts,但是因为一 ...
相关推荐
"小程序自定义分页选择组件"是一个专门为解决页面分页问题而设计的组件,它提供了灵活的配置选项,允许开发者根据实际需求定制分页显示效果。下面我们将深入探讨这个组件的核心功能、参数设置以及如何在小程序中应用...
QT自定义分页组件是软件开发中常见的设计模式,特别是在GUI应用中,用于展示大量数据时,分页能有效提高用户体验。在这个项目中,我们有`qt自定义分页组件源代码`,它包含了实现这一功能的核心源码和测试代码。下面...
自定义分页标签自定义分页标签自定义分页标签自定义分页标签自定义分页标签自定义分页标签自定义分页标签自定义分页标签自定义分页标签自定义分页标签自定义分页标签自定义分页标签自定义分页标签自定义分页标签...
使用`BindingSource`组件可以方便地实现数据绑定和分页操作。 4. **分页逻辑**:在事件处理程序中,你需要实现分页逻辑。这通常涉及计算当前页码、确定数据范围,然后更新数据显示。例如,如果每页显示10条数据,第...
2.1.目前网络上很多分页主键,不能进行按钮选择, 2.2.甚至对样式修改的难度也较大, 2.3.使用在开发过程中由于使用到了分页功能,在这里写了一个分页功能。 3.按钮选择 之前的很多按钮是通过参数进行选择,这样不...
本文将深入探讨如何在ASP.NET中实现自定义分页,以及与SQL数据库的集成。 首先,我们要理解ASP.NET中的分页原理。分页的基本思想是通过在服务器端对数据进行切割,每次只取一部分数据返回给客户端,然后在客户端...
为了提高代码的可维护性和可移植性,我们可以通过编写自定义分页插件来实现更灵活的分页逻辑。本文将详细介绍如何在 MyBatis 中实现自定义分页插件。 自定义分页插件提供了一种灵活且高效的方式来实现 MyBatis 的...
首先,分页控件是数据展示的核心组件,尤其是在大数据集的场景下。通过分页,用户可以逐页浏览数据,而不是一次性加载所有记录,这大大减轻了服务器的压力,提升了网页加载速度。.NET框架提供了一些内置的分页控件,...
实现自定义分页控件通常涉及以下几个关键组件: 1. **基类选择**:你可以选择继承`QWidget`或`QAbstractButton`作为自定义控件的基础。如果需要一个完整的组件,可以选择`QWidget`,因为它提供了一个空白画布,可以...
LibHelper是一个支持自定义分页的工具类,详细介绍看这里 “MVC实现自定义分页”http://blog.csdn.net/xyj2014/article/details/49761963
然而,标准的GridView控件默认的分页功能可能无法满足所有用户的需求,这时我们需要自定义分页来提供更加灵活和个性化的用户体验。本文将深入探讨如何在GridView中实现自定义分页,以及这一过程中的关键知识点。 ...
本文实例为大家分享了swiper自定义分页器的样式代码,供大家参考,具体内容如下 js主要代码 pagination: { // 自定义分页器的类名----必填项 el: '.custom-pagination', // 是否可点击----必填项 clickable: ...
在Java开发中,自定义分页标签是一种常见的需求,它能帮助我们构建用户友好的界面,使得大量数据的展示变得更加高效和便捷。本教程将详细讲解如何创建和使用自定义分页标签,以及如何实现淘宝购物分页标签的样式。 ...
本教程将深入探讨如何在Android中创建一个自定义分页控件,以便实现高效、用户友好的界面。 首先,我们需要理解分页的基本原理。分页通常是通过在后台服务器上对数据进行切片,每次请求只加载一部分数据,而不是一...
在Angular2中,自定义分页组件是一种常见的需求,它能帮助用户更高效地浏览大量数据。本篇文章将深入探讨如何在Angular2中创建并使用一个自定义分页组件。 首先,我们需要理解分页的基本原理。分页通常涉及到以下几...
这个资源是一个基于vue2和element-ui实现的自定义分页表格组件,是将element-ui的表格组件和分页组件封装成了一个组件,可以指定接口地址,快速实现分页表格的渲染,减少前端代码的编写。使用的技术:vue2.6.14、...
本文将详细介绍如何创建一个自定义的分页控件,并通过Web版实例进行演示。 一、分页控件的基本概念 分页控件是网页设计中用于分割大量数据的一种交互组件,它允许用户通过点击不同页码来查看数据的不同部分。分页...