вторник, 29 июля 2008 г.

JBoss richfaces and true pagination (paging) [ENG]

Offcouse richfaces has own implimintation of paging component - rich:datascroller.
But it's manipulate only already fetching data, and every click send request to bean where probably you fetch data from database.
It is NOT true paging mechanism.
Let's me introduce my own (may be not clear, but fully working) paging.
What we must has, lets see: richfaces, jboss seam and offcouce facelets.
Start with facelets custom tag.
we has some facelets tag configuration file, for example: icust.taglib.xml
and must describe it in web.xml

<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>
/WEB-INF/icust.taglib.xml
</param-value>
</context-param>

in this configuration file, simply specify file name wich contains our tag.
For more information about facelets read facelets documentation

<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "facelet-taglib_1_0.dtd">
<facelet-taglib>
<namespace>http://www.icust.ru/jsf</namespace>
<tag>
<tag-name>paging</tag-name>
<source>paging.xhtml</source>
</tag>
</facelet-taglib>

ok! we finish configure our tag =) lets see the tag code

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:f="http://java.sun.com/jsf/core">

<c:set var="maxpage" value="9"/>
<c:set var="interval" value="4"/>

<c:if test="${!empty errorlabel}">
<div>
<h:outputText value="#{errorlabel}" escape="false" styleClass="error"/>
</div>
</c:if>
<c:if test="${pagecount ge 2}">
<c:if test="#{! empty page}">
<c:set var="stop" value="${page + interval}" />
<c:if test="${stop le pagecount}">
<c:set var="stop" value="${page + interval}" />
<c:set var="start" value="${page - interval}" />
</c:if>
<c:if test="${stop ge pagecount}">
<c:set var="stop" value="${pagecount}" />
<c:set var="start" value="${pagecount - (2 *interval)}" />
</c:if>
<c:if test="${start le 2}">
<c:set var="start" value="1" />
<c:set var="stop" value="${maxpage}" />
</c:if>
</c:if>
<c:if test="#{page eq 0}">
<c:set var="start" value="1" />
<c:set var="stop" value="${maxpage}" />
<c:set var="page" value="1" />
</c:if>
<c:if test="#{stop ge pagecount}">
<c:set var="stop" value="${pagecount}" />
</c:if>
<div style="width: 100%; height: 27px; margin-top: 9px;">
<div style="float: left;">
<h:outputText value="#{label}"/>
</div>
<div style="float: right;">
<ul class="paging">
<c:if test="#{! (start eq 1)}">
<li>
<h:outputLink value="${url}&pageNo=" styleClass="pagingf">
<h:outputText value="←" escape="false"/>
</h:outputLink>
</li>
</c:if>
<c:forEach var="i" begin="${start}" end="${stop}">
<li>
<c:if test="#{page ne i}">
<h:outputLink value="${url}&pageNo=${i}">
<h:outputText value="${i}"/>
</h:outputLink>
</c:if>
<c:if test="#{page eq i}">
<h:outputLink value="#" styleClass="current">
<h:outputText value="${i}"/>
</h:outputLink>
</c:if>
</li>
</c:forEach>
<c:if test="#{(stop + 1) le pagecount}">
<li>
<h:outputLink value="${url}&pageNo=${pagecount}" styleClass="pagingl">
<h:outputText value="→" escape="false"/>
</h:outputLink>
</li>
</c:if>
</ul>
</div>
</div>
</c:if>
</ui:composition>

us you can see in code we has some additional parameters:
pagecount - total count pages
page - current page number
url - url for paging generate
errorlabel - label for nothing found
and
label - for found (possible found items) message
if page you place tag, for example:
<icust:paging pagecount="#{VideoList.paging.count}" page="#{VideoList.paging.current}" url="#{VideoList.paging.url}" errorlabel="#{VideoList.paging.errorlabel}" label="#{VideoList.paging.label}"/>

you need create simple Paging.class and initialize it in you bean.

public class Paging {
private int count;
private int current;
private String url;
private String label;
private String errorlabel;

public Paging() {
}

public Paging(int count, int current) {
this.count = count;
this.current = current;
}

public int getCurrent() {
return current;
}

public void setCurrent(int current) {
this.current = current;
}

public int getCount() {
return count;
}

public void setCount(int count) {
this.count = count;
}

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}

public String getLabel() {
return label;
}

public void setLabel(String label) {
this.label = label;
}

/**
* view error label only one
*
* @return
*/
public String getErrorlabel() {
String error = errorlabel;
return error;
}

public void setErrorlabel(String errorlabel) {
this.errorlabel = errorlabel;
}
}

request parameter for page number is pageNo
in bean you can get it by seam annotation:

@RequestParameter
private Integer pageNo;

in page you must create Paging instance BEFORE get value for table.

if you can simplify my solution you are welcome.

Working example you can see here:
http://dev.maryno.net/video/list.html?data=

some css styles for good look:

.paging {
font-size: 75%;
font-family: Arial, sans-serif;
display: inline;
list-style: none;
text-decoration: none;
}

.paging li {
display: inline;
}

.paging a {
padding: 6px 10px 6px 10px;
background: #fff;
text-align: center;
border: 1px solid #beb1b1;
text-decoration: none;
color: #777 !important;
margin-right: 2px;
margin-left: 2px;
height: 25px;
}

.paging a:HOVER {
text-decoration: none;
background: #e6e6e6;
}

.paging a.current {
border: 1px solid #beb1b1;
font-weight: bold;
background: #969696;
color: #fff !important;
}

.paging a.pagingf {
padding: 6px 8px 6px 8px;
margin-right: 8px;
}

.paging a.pagingl {
padding: 6px 8px 6px 8px;
margin-left: 8px;
}

Комментариев нет: