0

ZK Custom Pagination and Sorting

asked 2011-03-23 14:43:51 +0800

vradiya gravatar image vradiya
33 1

Hello all,

I am facing a very small but strange issue while working on Custom pagination and Sorting. Pagination and Sorting both works fine but the only problem is when I sort the data, result on a first page display in a reverse direction.
e.g. I am on page 5 and clicked on header ID.

Descending Order Result
Data I am Expecting : 1260,1259,1258,1257,1256,1255......
Data it is showing right now: 1255,1256,1257,1258,1259,1260
Icon on a header changed to descending...

Ascending Order Result
Data I am Expecting : 1255,1256,1257,1258,1259,1260
Data it is showing right now: 1260,1259,1258,1257,1256,1255......
Icon on a header changed to ascending...

I got redirected to very first page, which is fine. Once I sort the data and navigate to next page (Page #2) and come back to page #1 then everything is in a order the way I want..i.e. 1260,1259,1258,1257,1256,1255......

I am unable to understand what thing I am doing wrong while sorting. Please take a look at the code below and any suggestions will be highly appreciated.

thanks ...Vish

TagsContoller.java


import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import org.zkoss.lang.Strings;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.ext.AfterCompose;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Listhead;
import org.zkoss.zul.Listheader;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.Paging;
import org.zkoss.zul.event.PagingEvent;


public class TagsContoller extends SimpleWindow implements AfterCompose {

  	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private final String LST_TAGS = "lstTags";
	private final String PAG_TAGS = "pagTag";
	private String ASCENDING = "ascending";
	private String DESCENDING = "descending";
	private String NATURAL = "natural";
	private String DATE_FORMAT = "yyyy/MM/dd HH:mm:ss";
	private boolean ascending = true;
	Listhead listhead;
	Listbox lstTags;
	
	private String getHeaderLabel(String label){
		
		if(label != null && label.equalsIgnoreCase("Timestamp")){
        	return TagBlinkCache.TIMESTAMP_SEC_INDEX;
        }else if(label != null && label.equalsIgnoreCase("x")){
        	return TagBlinkCache.LOC_X_INDEX;
        }else if(label != null && label.equalsIgnoreCase("y")){
        	return TagBlinkCache.LOC_Y_INDEX;
        }else if(label != null && label.equalsIgnoreCase("z")){
        	return TagBlinkCache.LOC_Z_INDEX;
        }else if(label != null && label.equalsIgnoreCase("Exciter Id")){
        	return TagBlinkCache.STATION_ID_INDEX;
        }else{
        	return TagBlinkCache.TAG_ID_INDEX;
        }
	}
	public void redrawForAscDesc(String indexId){
		
        List<TagBlink> list1 = TagBlinkCache.getInstance().getList(indexId);
        
		Paging pag = getPaging(PAG_TAGS);
		pag.setTotalSize(list1.size());
		
		final int PAGE_SIZE = pag.getPageSize();
		
		// Show Listbox with first PAGE_SIZE		
		redraw(0, PAGE_SIZE,list1,true);
		pag.setActivePage(0);
	}
	public void onSortEventListener(Event event) {
        
            final Listheader lh = (Listheader) event.getTarget();
            final String sortDirection = lh.getSortDirection();
            String indexId = "";
            if (ASCENDING.equals(sortDirection)) {
            	ascending = true;
            	indexId = getHeaderLabel(lh.getLabel());
            	redrawForAscDesc(indexId);
            } else if (DESCENDING.equals(sortDirection) || NATURAL.equals(sortDirection) || Strings.isBlank(sortDirection)) {
            		ascending = false;
            		indexId = getHeaderLabel(lh.getLabel());
            		redrawForAscDesc(indexId);
            }
    }
    
	@SuppressWarnings("unchecked")
	public void afterCompose() {
		lstTags = getListbox(LST_TAGS);
		Listhead listhead = lstTags.getListhead();
        List<Listheader> list = listhead.getChildren();
 
        for (Object object : list) {
            if (object instanceof Listheader) {
                Listheader lheader = (Listheader) object;
               
                if (lheader.getSortAscending() != null || lheader.getSortDescending() != null) {
 
                    lheader.addEventListener("onSort", new EventListener() {
            			public void onEvent(Event event) {
            				onSortEventListener(event);
            			}
            		});
                }
            }
        }
		
		String indexId = "tagId_INDEX";
		final List<TagBlink> list1 = TagBlinkCache.getInstance().getList(indexId);
		
		Paging pag = getPaging(PAG_TAGS);
		pag.setTotalSize(list1.size());
		
		final int PAGE_SIZE = pag.getPageSize();
		
		// Show Listbox with first PAGE_SIZE		
		redraw(0, PAGE_SIZE,list1,false);

		pag.addEventListener(org.zkoss.zul.event.ZulEvents.ON_PAGING, new EventListener() {
			public void onEvent(Event event) {
				PagingEvent pe = (PagingEvent) event;
				int pgno = pe.getActivePage();
				int ofs = pgno * PAGE_SIZE;
				// Redraw current paging
				redraw(ofs, PAGE_SIZE,list1,false);
			}
		});
	}
	
	private void redraw(int firstResult, int maxResults, List<TagBlink> list1,boolean sorting) {
		
		RangeFinder.Range range;
		List<TagBlink> subList;
		synchronized (list1) {
			range = RangeFinder.findRange(list1, firstResult,
					maxResults, ascending);
			try {
				subList = list1.subList(range.getFromIndex(), range.getToIndex());
			} catch (IndexOutOfBoundsException e) {
				subList = new ArrayList<TagBlink>();
			}
		}
		
		Listbox lst = getListbox(LST_TAGS);
		lst.getItems().clear();

		SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT);
		
		for (TagBlink tagBlink : subList) {
			
			Listitem li = new Listitem();
			li.setValue(tagBlink);
			li.appendChild(new Listcell("" + tagBlink.getSource()));
			li.appendChild(new Listcell(tagBlink.getFormat()));
			li.appendChild(new Listcell(tagBlink.getId()));
			li.appendChild(new Listcell(tagBlink.getX()+""));
			li.appendChild(new Listcell(tagBlink.getY()+""));
			li.appendChild(new Listcell(tagBlink.getZ()+""));
			li.appendChild(new Listcell(tagBlink.getBattery()+""));
			li.appendChild(new Listcell(tagBlink.getStationId()+""));
			li.appendChild(new Listcell(tagBlink.getStatus()+""));
			Date date = new Date(tagBlink.getTimestampMillis());
			li.appendChild(new Listcell(df.format(date)));
			lst.appendChild(li);
		}
	}
}


tags.zul

<?xml version="1.0" encoding="UTF-8"?>
<?page id="zkHome" title="ZK Demo"?>
<?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c"?>
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" arg0="./cTags"?>

<zk xmlns="http://www.zkoss.org/2005/zul">

<style src="../style/zls-console.css"></style>
<style>
	div.z-grid-body{
		background: white; border: 0; overflow: auto; width: 100%;
	}
	
</style>

	
<window width="100%" id="cTags"
	border="none" use="TagsContoller"
	xmlns:zk="http://www.zkoss.org/2005/zul"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:n="http://www.zkoss.org/2005/zk/native"
	xsi:schemaLocation="http://www.zkoss.org/2005/zul http://www.zkoss.org/2005/zul/zul.xsd">
	<n:script type="text/javascript"><![CDATA[
			function screenResolution(){
				if(screen.height == 1024)
					zk.Widget.$(jq('$lstTags')[0]).setStyle('height:710px');
				else if(screen.height == 864)
					zk.Widget.$(jq('$lstTags')[0]).setStyle('height:635px');
				else if(screen.height == 768)
					zk.Widget.$(jq('$lstTags')[0]).setStyle('height:540px');
				else if(screen.height == 600)
					zk.Widget.$(jq('$lstTags')[0]).setStyle('height:375px');	
						
	        }
        ]]>
  		</n:script>
	<attribute name="onCreate"><![CDATA[
      Clients.evalJavaScript("screenResolution()");        
    ]]></attribute>
    
		<toolbar align="end"><div height="23px">
		</div></toolbar> 
	<div>
			<zk:listbox id="lstTags" vflex="true" style="height:540px" hflex="true">
				<zk:listhead sizable="true">
					<zk:listheader label="Source"/>
					<zk:listheader label="Format"/>
					<zk:listheader label="Tag Id" sort="auto" />
					<zk:listheader label="x" sort="auto"  width="5%"/>
					<zk:listheader label="y" sort="auto"  width="5%"/>
					<zk:listheader label="z" sort="auto"  width="5%"/>
					<zk:listheader label="Battery" width="10%"/>
					<zk:listheader label="Exciter Id" sort="auto"  width="10%"/>
					<zk:listheader label="Status" width="10%"/>
					<zk:listheader label="Timestamp" sort="auto" />
				</zk:listhead>
			</zk:listbox>
			<zk:paging id="pagTag" pageSize="25"/>
	</div>	
</window>	
</zk>


p.s. I debugged the code and also put Sys.out when it fill the list..it is filling the list in a correct order but while displaying on a page(.zul) it just comes out in a reverse order. Is this because I am having sort="auto" or ZUL page?

delete flag offensive retag edit

7 Replies

Sort by ยป oldest newest

answered 2011-03-23 16:42:19 +0800

vradiya gravatar image vradiya
33 1

okay..I kind of figure it out..I just replaced above listbox with below and things started working..

<div>
			<zk:listbox id="lstTags" vflex="true" style="height:540px" hflex="true">
				<zk:listhead sizable="true">
					<zk:listheader label="Source"/>
					<zk:listheader label="Format"/>
					<zk:listheader label="Tag Id" sort="auto(id)" />
					<zk:listheader label="x" sort="auto(x)"  width="5%"/>
					<zk:listheader label="y" sort="auto(y)"  width="5%"/>
					<zk:listheader label="z" sort="auto(z)"  width="5%"/>
					<zk:listheader label="Battery" width="10%"/>
					<zk:listheader label="Exciter Id" sort="auto(stationId)"  width="10%"/>
					<zk:listheader label="Status" width="10%"/>
					<zk:listheader label="Timestamp" sort="auto(timestampMillis)" />
				</zk:listhead>
			</zk:listbox>
			<zk:paging id="pagTag" pageSize="25"/>
	</div>	

as I said I kind of figure out..If I sort by Id then it looks okay as Id in my Object (TagBlink) is String.. X, Y, Z are double and timestamp is long..
how do I pass double, long and int into Listcell for comparison?

anyone??

thanks

Vish

link publish delete flag offensive edit

answered 2011-03-23 19:05:43 +0800

vradiya gravatar image vradiya
33 1

It's behaving really weird now..above code works when I sort by ID..then I tried sorting by X, Y, Z and timestamp and it threw below error..

Mar 23, 2011 4:58:50 PM org.zkoss.zk.ui.impl.UiEngineImpl handleError:1253
SEVERE: >>org.zkoss.zk.ui.UiException: java.lang.NoSuchMethodException: class org.zkoss.zul.Listitem: name=timestampMillis args=null
>>java.lang.NoSuchMethodException: class org.zkoss.zul.Listitem: name=timestampMillis args=null
>>	at org.zkoss.lang.Classes.myGetAcsObj(Classes.java:968)
>>	at org.zkoss.lang.Classes.getAccessibleObject(Classes.java:893)
>>	at org.zkoss.lang.reflect.Fields.get(Fields.java:114)
>>	at org.zkoss.lang.reflect.Fields.getByCompound(Fields.java:61)
>>	at org.zkoss.zul.FieldComparator.compare0(FieldComparator.java:119)
>>	at org.zkoss.zul.FieldComparator.compare(FieldComparator.java:82)

can anyone guide me in the right direction please?

thanks

link publish delete flag offensive edit

answered 2011-03-25 12:36:43 +0800

vradiya gravatar image vradiya
33 1

hello everyone..can anyone post some sample code for custom sorting on each column?. as I said above code only works for sorting by ID...

thanks

link publish delete flag offensive edit

answered 2011-03-25 15:25:12 +0800

Matze2 gravatar image Matze2
773 7

updated 2011-03-25 15:28:07 +0800

A wild guess: sorting by id column works because Listitem has an "id" bean property.

link publish delete flag offensive edit

answered 2011-03-30 00:01:07 +0800

henrichen gravatar image henrichen
3869 2
ZK Team

updated 2011-03-30 00:05:48 +0800

@vradiya,

From your source code, it seems you don't associate a ListModel with the Listbox? Then the auto(xyz) mechanism will be applied onto the Listitem itself rather than the object in ListModel. The auto(xyz) assumes a getXyz() in the Object/Listitem and compare them for sorting purpose. So Matze2's guess is correct. The stack trace:

SEVERE: >>org.zkoss.zk.ui.UiException: java.lang.NoSuchMethodException: class org.zkoss.zul.Listitem: name=timestampMillis args=null

says the ZK engine try to find a getTimestampMillis() method on Listitem, but it cannot find it.

Here is a simple example you might like to take a look:

http://books.zkoss.org/wiki/Small_Talks/2009/March/New_Features_of_ZK_3.6.0#Listbox_supports_auto-sorting_on_fields

And this is an advanced example on how to load huge data with sorting and paging.

http://books.zkoss.org/wiki/Small_Talks/2011/March/Sorting_huge_data_using_ZK

link publish delete flag offensive edit

answered 2011-04-13 12:16:34 +0800

vradiya gravatar image vradiya
33 1

Hello henrichen, thanks for your comment. I will look into those links.

link publish delete flag offensive edit

answered 2013-09-08 09:08:51 +0800

mefiu gravatar image mefiu
1 1

updated 2013-09-08 09:10:58 +0800

I have the very same problem. Sorting works for all my columns columns, but the first page is always reversed after the sort order is changed (by clicking on a list column header). When I switch the page forward and back, the sort is OK again. Is there a clear solution to this problem? The discussion so far doesn't mention one...

link publish delete flag offensive edit
Your reply
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow

RSS

Stats

Asked: 2011-03-23 14:43:51 +0800

Seen: 1,618 times

Last updated: Sep 08 '13

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More