0

Access all rows of a listbox

asked 2012-03-01 12:17:50 +0800

Neus gravatar image Neus
1415 14

Hi,
I have a function that converts any listbox to excel. It goes through all listitems, access its cells and write its label to an StringBuffer.
The lisitems in pages that the user hasn't yet visit are not rendered. That's why since now I was doing listbox.renderItem((Listitem) item) in the loop that browse the lisitems.
But since I update to ZK 6 doing listbox.renderItem((Listitem) item) throws an exception

java.util.ConcurrentModificationException
	at org.zkoss.zk.ui.AbstractComponent$ChildIter.checkComodification(AbstractComponent.java:2848)
	at org.zkoss.zk.ui.AbstractComponent$ChildIter.next(AbstractComponent.java:2826)
	at org.zkoss.zk.ui.AbstractComponent$ChildIter.next(AbstractComponent.java:2797)
	at org.zkoss.zul.Listbox$ItemIter.next(Listbox.java:2852)
	at org.zkoss.zul.Listbox$ItemIter.next(Listbox.java:2824)
	at org.sts.generales.Herramientas.funcionesTablas.PasarExcel(funcionesTablas.java:97)
	at org.sts.generales.PlantillasZul.SeguimientoSelector.PasarExcel(SeguimientoSelector.java:801)

This is my loop code:
 for (Object item : oListBox.getItems()) {
        	//Los tenemos que ir cargando porque los items de las páginas que no se hayan visitado
        	//no estarán cargados
	    	oListBox.renderItem((Listitem) item);
	        String i = "";
	        for (Object cell : ((Listitem) item).getChildren()) {
	        	//Solo mostramos las celdas que estén visibles
	        	if(((Listcell)cell).getListheader()!=null){
		        	 if(((Listcell)cell).getListheader().isVisible()){
		        		 i += ((Listcell) cell).getLabel() + puntoYComa;
		        	 }
	        	}
	        }
	        sb.append(i + "\n");
        }

Another idea to access all listitems of the listbox?Or some way to solve this?

Thank you!

delete flag offensive retag edit

5 Replies

Sort by » oldest newest

answered 2012-03-06 11:33:43 +0800

benbai gravatar image benbai
2228 6
http://www.zkoss.org

Hi,

I run your code without any exception but it only loop through first 100 items with ROD,
you may try Listbox#renderAll(), please refer to the samples:

original case:

ZKFiddle-Link

index.zul
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>
<zk>
<!--
#############################################
# #
# original, fail, #
# problem is only access first 100 item #
# #
#############################################
-->
<zscript><![CDATA[
class Person {
private String firstName;
private String lastName;
private int age;

public Person(String f, String l) {
firstName = f;
lastName = l;
}

public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getFullName() {
return firstName + " " + lastName;
}
}

java.util.List persons = new java.util.ArrayList(8);
for (int i = 0; i < 300; i++) {
persons.add(new Person("first name "+i, "last name " +i));
}

ListModelList lm = new ListModelList(persons);
class AvoidingDuplicateRenderer implements ListitemRenderer {
private String _type;
private List _rendered = new ArrayList();
public void render(Listitem listitem, Object data, int index) {
Person p = (Person)data;
String label = "first".equals(_type)? p.getFirstName() : p.getLastName();
if (_rendered.contains(label)) {
listitem.setParent(null);
} else {
listitem.setLabel(label);
_rendered.add(label);
}
}
public void setType (String type) {
_type = type;
}
}
AvoidingDuplicateRenderer adrOne = new AvoidingDuplicateRenderer();
AvoidingDuplicateRenderer adrTwo = new AvoidingDuplicateRenderer();
adrOne.setType("first");
]]></zscript>
<listbox id="oListBox" model="@{lm}" height="200px">
<listhead>
<listheader label="First Name" />
<listheader label="Last Name" />
</listhead>
<listitem self="@{each=person}">
<listcell label="@{person.firstName}"/>
<listcell label="@{person.lastName}"/>
</listitem>
</listbox>
<button label="test">
<attribute name="onClick">
StringBuilder sb = new StringBuilder("");
for (Object item : oListBox.getItems()) {
//Los tenemos que ir cargando porque los items de las p��ginas que no se hayan visitado
//no estar��n cargados
oListBox.renderItem((Listitem) item);
String i = "";
for (Object cell : ((Listitem) item).getChildren()) {
//Solo mostramos las celdas que est��n visibles
if(((Listcell)cell).getListheader()!=null){
if(((Listcell)cell).getListheader().isVisible()){
i += ((Listcell) cell).getLabel() + puntoYComa;
}
}
}
sb.append(i + "\r\n");
}
lb.setValue(sb.toString());
</attribute>
</button>
<textbox rows="6" width="300px" id="lb" value="message: " />
</zk>

use renderAll:


index.zul
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>
<zk>
<!--
#############################################
# #
# renderall, success #
# #
#############################################
-->
<zscript><![CDATA[
class Person {
private String firstName;
private String lastName;
private int age;

public Person(String f, String l) {
firstName = f;
lastName = l;
}

public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getFullName() {
return firstName + " " + lastName;
}
}

java.util.List persons = new java.util.ArrayList(8);
for (int i = 0; i < 300; i++) {
persons.add(new Person("first name "+i, "last name " +i));
}

ListModelList lm = new ListModelList(persons);
class AvoidingDuplicateRenderer implements ListitemRenderer {
private String _type;
private List _rendered = new ArrayList();
public void render(Listitem listitem, Object data, int index) {
Person p = (Person)data;
String label = "first".equals(_type)? p.getFirstName() : p.getLastName();
if (_rendered.contains(label)) {
listitem.setParent(null);
} else {
listitem.setLabel(label);
_rendered.add(label);
}
}
public void setType (String type) {
_type = type;
}
}
AvoidingDuplicateRenderer adrOne = new AvoidingDuplicateRenderer();
AvoidingDuplicateRenderer adrTwo = new AvoidingDuplicateRenderer();
adrOne.setType("first");
]]></zscript>
<listbox id="oListBox" model="@{lm}" height="200px">
<listhead>
<listheader label="First Name" />
<listheader label="Last Name" />
</listhead>
<listitem self="@{each=person}">
<listcell label="@{person.firstName}"/>
<listcell label="@{person.lastName}"/>
</listitem>
</listbox>
<button label="test">
<attribute name="onClick">
StringBuilder sb = new StringBuilder("");
oListBox.renderAll();
for (Object item : oListBox.getItems()) {
String i = "";
for (Object cell : ((Listitem) item).getChildren()) {
//Solo mostramos las celdas que est��n visibles
if(((Listcell)cell).getListheader()!=null){
if(((Listcell)cell).getListheader().isVisible()){
i += ((Listcell) cell).getLabel() + puntoYComa;
}
}
}
sb.append(i + "\r\n");
}
lb.setValue(sb.toString());
</attribute>
</button>
<textbox rows="6" width="300px" id="lb" value="message: " />
</zk>

Regards,
Ben

link publish delete flag offensive edit

answered 2012-03-13 08:59:55 +0800

Neus gravatar image Neus
1415 14
I reproduced my real code in Fiddle: [fiddle height="300" sample="http://zkfiddle.org/sample/64ovvp/2-Access-all-list-item" /] I realize that the first time you click the button items are not rendered but if you click it by second time they can be accessed. How can this be solved?
link publish delete flag offensive edit

answered 2012-03-19 09:53:15 +0800

benbai gravatar image benbai
2228 6
http://www.zkoss.org

Hi,

You may disable the ROD by

<custom-attributes org.zkoss.zul.listbox.rod="false"/>

or try get the value from model directly:

ZKFiddle-Link

Person.java
package j64ovvp$v3;

import org.zkoss.zk.ui.*;
import org.zkoss.zk.ui.event.*;
import org.zkoss.zk.ui.util.*;
import org.zkoss.zk.ui.ext.*;
import org.zkoss.zk.au.*;
import org.zkoss.zk.au.out.*;
import org.zkoss.zul.*;

public class Person{
private String firstName;
private String lastName;
private int age;

public Person(String f, String l) {
firstName = f;
lastName = l;
}

public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getFullName() {
return firstName + " " + lastName;
}

}


test.java
package j64ovvp$v3;

import org.zkoss.zk.ui.*;
import org.zkoss.zk.ui.event.*;
import org.zkoss.zk.ui.util.*;
import org.zkoss.zk.ui.ext.*;
import org.zkoss.zk.au.*;
import org.zkoss.zk.au.out.*;
import org.zkoss.zul.*;
import org.zkoss.zk.ui.select.annotation.*;
import org.zkoss.bind.annotation.*;
public class test{
java.util.List persons = new java.util.ArrayList(8);
@Command @NotifyChange("persons")
public void Cargar(){
for (int i = 0; i < 300; i++) {
persons.add(new Person("first name "+i, "last name " +i));
}
}

public java.util.List getPersons(){
return persons;
}
}


index.zul
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>
<zk>
<div apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('j64ovvp$v3.test')" onCreate="@command('Cargar')">
<listbox id="oListBox" model="@load(vm.persons)" height="200px" mold="paging" autopaging="true">
<listhead>
<listheader label="First Name" />
<listheader label="Last Name" />
</listhead>
<template name="model" var="item">
<listitem>
<listcell label="@load(item.firstName)"/>
<listcell label="@load(item.lastName)"/>
</listitem>
</template>
</listbox>
<button label="test">
<attribute name="onClick">
StringBuilder sb = new StringBuilder("");
oListBox.renderAll();
alert("items->"+oListBox.getItemCount());
int itemCnt = 0;

for (Object item : oListBox.getItems()) {
String i = "";

for (Object cell : ((Listitem) item).getChildren()) {
//Solo mostramos las celdas que esten visibles
Listheader lh = ((Listcell)cell).getListheader();
if(lh!=null){
if(lh.isVisible()){
j64ovvp$v3.Person p = (j64ovvp$v3.Person)oListBox.getModel().getElementAt(itemCnt);
if ("First Name".equals(lh.getLabel()))
i += p.getFirstName() + ";";
if ("Last Name".equals(lh.getLabel()))
i += p.getFirstName() + ";";
}
}
}
sb.append(i + "\r\n");
itemCnt++;
}
lb.setValue(sb.toString());
</attribute>
</button>
<textbox rows="6" width="300px" id="lb" value="message: " />
</div>
</zk>

Regards,
Ben

link publish delete flag offensive edit

answered 2012-03-20 09:36:55 +0800

Neus gravatar image Neus
1415 14

I can't use model directly because is a general function used to pass any listbox to excel.
If I disable ROD all items will be rendered from the begining and this is a big waste of memory. If user wants to extract data to excel and render all items of that listbox is his choice.
Before using ZK Bind 6 use the RenderAll works (it can be checked in your first fiddle examples). Why now it is changed?

link publish delete flag offensive edit

answered 2012-03-20 11:33:43 +0800

benbai gravatar image benbai
2228 6
http://www.zkoss.org

It seems caused by the timing issue,
a quick workaround is to start a timer after renderAll:

ZKFiddle-Link

Person.java
package j64ovvp$v4;

import org.zkoss.zk.ui.*;
import org.zkoss.zk.ui.event.*;
import org.zkoss.zk.ui.util.*;
import org.zkoss.zk.ui.ext.*;
import org.zkoss.zk.au.*;
import org.zkoss.zk.au.out.*;
import org.zkoss.zul.*;

public class Person{
private String firstName;
private String lastName;
private int age;

public Person(String f, String l) {
firstName = f;
lastName = l;
}

public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getFullName() {
return firstName + " " + lastName;
}

}


test.java
package j64ovvp$v4;

import org.zkoss.zk.ui.*;
import org.zkoss.zk.ui.event.*;
import org.zkoss.zk.ui.util.*;
import org.zkoss.zk.ui.ext.*;
import org.zkoss.zk.au.*;
import org.zkoss.zk.au.out.*;
import org.zkoss.zul.*;
import org.zkoss.zk.ui.select.annotation.*;
import org.zkoss.bind.annotation.*;
public class test{
java.util.List persons = new java.util.ArrayList(8);
@Command @NotifyChange("persons")
public void Cargar(){
for (int i = 0; i < 300; i++) {
persons.add(new Person("first name "+i, "last name " +i));
}
}

public java.util.List getPersons(){
return persons;
}
}


index.zul
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>
<zk>
<div apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('j64ovvp$v4.test')" onCreate="@command('Cargar')">
<listbox id="oListBox" model="@load(vm.persons)" height="200px" mold="paging" autopaging="true">
<listhead>
<listheader label="First Name" />
<listheader label="Last Name" />
</listhead>
<template name="model" var="item">
<listitem>
<listcell label="@load(item.firstName)"/>
<listcell label="@load(item.lastName)"/>
</listitem>
</template>
</listbox>
<button label="test">
<attribute name="onClick">
oListBox.renderAll();
timer.start();
</attribute>
</button>

<timer id="timer" delay="10" repeats="false" running="false">
<attribute name="onTimer">
StringBuilder sb = new StringBuilder("");

alert("items->"+oListBox.getItemCount());
for (Object item : oListBox.getItems()) {
String i = "";
for (Object cell : ((Listitem) item).getChildren()) {
//Solo mostramos las celdas que est��n visibles
if(((Listcell)cell).getListheader()!=null){
if(((Listcell)cell).getListheader().isVisible()){
i += ((Listcell) cell).getLabel() + ";";
}
}
}
sb.append(i + "\r\n");
}
lb.setValue(sb.toString());
</attribute>
</timer>
<textbox rows="6" width="300px" id="lb" value="message: " />
</div>
</zk>

Regards,
Ben

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: 2012-03-01 12:17:50 +0800

Seen: 352 times

Last updated: Mar 20 '12

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