-
FEATURED COMPONENTS
First time here? Check out the FAQ!
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)
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!
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:
<?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:
<?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
Hi,
You may disable the ROD by
<custom-attributes org.zkoss.zul.listbox.rod="false"/>
or try get the value from model directly:
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;
}
}
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;
}
}
<?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
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?
It seems caused by the timing issue,
a quick workaround is to start a timer after renderAll:
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;
}
}
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;
}
}
<?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
Asked: 2012-03-01 12:17:50 +0800
Seen: 358 times
Last updated: Mar 20 '12