-
FEATURED COMPONENTS
First time here? Check out the FAQ!
Hi,
with Z8 pagination does not work when the tree is built with the technical mvvm. Work only with zk 7.6 or old.
MY CODE:
<zk>
<window width="100%" border="none" apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('model.ViewModel')">
<tree model="@bind(vm.treeNodes)" mold="paging" pageSize="4">
<treecols sizable="true">
<treecol label="nome" width="120px" />
<treecol label="cognome" width="300px" />
</treecols>
<template name="model">
<treeitem open="@bind(each.open)">
<treerow>
<treecell label="@bind(each.data.name)"></treecell>
<treecell label="@bind(each.data.lastName)"></treecell>
<treecell>
</treecell>
</treerow>
</treeitem>
</template>
</tree>
</window>
</zk>
package model;
import java.util.LinkedList;
import org.zkoss.zul.DefaultTreeModel;
import org.zkoss.zul.TreeModel;
import org.zkoss.zul.TreeNode;
public class ViewModel {
private PersonTreeNode<Person> treeRoot=null;
private TreeModel<TreeNode<Person>> treeNodes=null;
public PersonTreeNode<Person> getTreeRoot() {
return treeRoot;
}
public void setTreeRoot(PersonTreeNode<Person> treeRoot) {
this.treeRoot = treeRoot;
}
public TreeModel<TreeNode<Person>> getTreeNodes() {
if ( this.treeRoot!=null )
this.treeNodes=new DefaultTreeModel<Person>(this.treeRoot);
return this.treeNodes;
}
public void setTreeNodes(TreeModel<TreeNode<Person>> treeNodes) {
this.treeNodes = treeNodes;
}
public PersonTreeNode<Person>addTreeNode(boolean open)
{
return this.addTreeNode( null, open);
}
public PersonTreeNode<Person> addTreeNode()
{
return this.addTreeNode( null, false);
}
public PersonTreeNode<Person> addTreeNode(PersonTreeNode<Person> parent)
{
return this.addTreeNode(parent, false);
}
public PersonTreeNode<Person> addTreeNode(PersonTreeNode<Person> parent,boolean open)
{
return this.addTreeNode(parent,open,null);
}
public PersonTreeNode<Person> addTreeNode(PersonTreeNode<Person> parent,boolean open,Integer pos)
{
if ( parent==null )
{
if ( this.treeRoot==null )
this.treeRoot=new PersonTreeNode<Person>(null,new LinkedList<PersonTreeNode<Person>>(),open);
parent=this.treeRoot;
}
Person row =new Person();
PersonTreeNode<Person> treeNode=null;
treeNode=new PersonTreeNode<Person>(parent,row,new LinkedList<PersonTreeNode<Person>>(),open,pos);
return treeNode;
}
@Init
public void init(){
this.loadDati();
}
public void loadDati()
{
Person row=null;
PersonTreeNode<Person> nodeParent;
PersonTreeNode<Person> node;
nodeParent=this.addTreeNode(true);
row=nodeParent.getData();
row.setLastName("Bianchi");
row.setName("Gino");
node=this.addTreeNode(nodeParent,true);
node.setLeaf(true);
row=node.getData();
row.setLastName("Rossi");
row.setName("Nino");
node=this.addTreeNode(nodeParent,true);
node.setLeaf(true);
row=node.getData();
row.setLastName("Verdi");
row.setName("Paolo");
node=this.addTreeNode(nodeParent,true);
node.setLeaf(true);
row=node.getData();
row.setLastName("Blues");
row.setName("Ugo");
node=this.addTreeNode(nodeParent,true);
node.setLeaf(true);
row=node.getData();
row.setLastName("Bianchio");
row.setName("Gianni");
}
}
package model;
import java.util.LinkedList;
import org.zkoss.zul.DefaultTreeNode;
public class PersonTreeNode<Persona> extends DefaultTreeNode<Persona> {
private static final long serialVersionUID = -8085873079938209759L;
// Node Control the default open
private boolean open = false;
private boolean leafNode=true;
public PersonTreeNode(Persona data, LinkedList<PersonTreeNode<Persona>> children, boolean open) {
super(data, children);
this.setOpen(open);
}
public PersonTreeNode(PersonTreeNode<Persona> parent,Persona data, LinkedList<PersonTreeNode<Persona>> children, boolean open) {
super(data, children);
this.setOpen(open);
parent.setLeaf(false);
parent.add(this);
}
public PersonTreeNode(PersonTreeNode<Persona> parent,Persona data, LinkedList<PersonTreeNode<Persona>> children, boolean open,Integer pos) {
super(data, children);
this.setOpen(open);
parent.setLeaf(false);
if (pos==null || parent.getChildren().size()==0 )
parent.add(this);
else
parent.getChildren().add(pos,this);
}
public PersonTreeNode(Persona data, LinkedList<PersonTreeNode<Persona>> children) {
super(data, children);
}
public PersonTreeNode(PersonTreeNode<Persona> parent,Persona data, LinkedList<PersonTreeNode<Persona>> children) {
super(data, children);
parent.setLeaf(false);
parent.add(this);
}
public PersonTreeNode(PersonTreeNode<Persona> parent,Persona data) {
super(data);
parent.setLeaf(false);
parent.add(this);
}
public PersonTreeNode(PersonTreeNode<Persona> parent,Persona data,boolean open) {
super(data);
parent.setLeaf(false);
parent.add(this);
this.setOpen(open);
}
public PersonTreeNode(Persona data) {
super(data);
}
public PersonTreeNode(Persona data,boolean open) {
super(data);
this.setOpen(open);
}
public boolean isOpen() {
return open;
}
public void setOpen(boolean open) {
this.open = open;
}
public boolean isLeaf() {
return leafNode;
}
public void setLeaf(boolean value) {
this.leafNode=value;
if ( value )
this.open=false;
}
}
package model;
public class Person {
private String name;
private String lastName;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
Pls help me????
The principle is: When you use a model for a component, you should manipulate a component with the model.
The reason is when you call component's API, it just controls its corresponding rendering on a browser but doesn't update the status in the model. But a component reacts to your interaction based on its model (if exists).
For example, you call Treeitem.setOpen(true)
, it just renders an open node and its children. But the node is still closed in the model. So when clicking the next page button, the component checks the model and find it's only 1 treeitem on the current page, so no more pages to switch. Hence, it looks like paging doesn't work.
Hello Luigi,
I confirm your issue: at the beginning i though there was an issue with your Java classes but then - using the simpleDefaultTreeNode and the way it is used here i reproduced the same issue.
Probably you still have an issue with the open property but it's not the one causing the major problem.
The morale is that i think you HAVE TO use a TreeitemRenderer and not the zul template: in fact if you comment the <template> block, you will see this.
UPDATE
Even with the TreeITemRenderer there are still issues when a list of children appears on the next page and their parent is on the previous one... really messy :(
KR Giovanni
Thanks you Giovanni,
if the problem is not corrected, I'll try to use TreeitemRenderer :)
Luigi Fabbri
I run your code without changing anything under 8.0.0 and 8.0.1.1 and works as expected.
What's the situation you met? it doesn't switch to the next page? In both ZK 7 an 8, you have to extend the root tree node, then the paging control shows. Then you can switch pages.
Yes it doesn't switch to the next page widt zk8, zk8.0.1 and zk 8.0.1.1, only it works if you close and reopen the root node. If you run the project and not close the root node the tree doesn't switch to the next page. With zk 7.6 or elder, work correctly without closing and reopening the root node.
The root cause is the node open status in the model is inconsistent with the Tree component. The basic principle is: when you use a model for a component, you should manipulate a component with the model.
You can try to open the root node like the code below, and you will find that switching pages works as expected.
public TreeModel<TreeNode<Person>> getTreeNodes() {
if (this.treeRoot != null){
this.treeNodes = new DefaultTreeModel<Person>(this.treeRoot);
//open the root in the model
((DefaultTreeModel)treeNodes).addOpenObject(treeRoot.getChildAt(0));
}
return this.treeNodes;
}
Hence, opening a node like <treeitem open="@bind(each.open)">
is incorrect, you should change the open status in your tree model.
Please also read ZK Dos and Donts
Tahnks you very much Hawk, i don't understand why <treeitem open="@bind(each.open)"> is incorrect, but your solution works perfectly. I'll try an answer by reading ZK Dos and Donts because for me ((DefaultTreeModel)treeNodes).addOpenObject(treeRoot.getChildAt(0)); is not very intuitive.
MY CORRECT CODE BELOW:
<zk>
<window width="100%" border="none" apply="org.zkoss.bind.BindComposer" viewmodel="@id('vm') @init('model.ViewModel')">
<tree model="@bind(vm.treeNodes)" mold="paging" pagesize="4">
<treecols sizable="true">
<treecol label="nome" width="120px"/>
<treecol label="cognome" width="300px"/>
</treecols>
<template name="model">
<treeitem>
<treerow>
<treecell label="@bind(each.data.name)"></treecell>
<treecell label="@bind(each.data.lastName)"></treecell>
<treecell>
</treecell>
</treerow>
</treeitem>
</template>
</tree>
</window>
</zk>
package model;
import java.util.LinkedList;
import org.zkoss.zul.DefaultTreeNode;
public class PersonTreeNode<persona> extends DefaultTreeNode<persona> {
private static final long serialVersionUID = -8085873079938209759L;
// Node Control the default open
private boolean open = false;
private boolean leafNode=true;
public PersonTreeNode(Persona data, LinkedList<PersonTreeNode<Persona>> children, boolean open) {
super(data, children);
this.setOpen(open);
}
public PersonTreeNode(PersonTreeNode<Persona> parent,Persona data, LinkedList<PersonTreeNode<Persona>> children, boolean open) {
super(data, children);
this.setOpen(open);
parent.setLeaf(false);
parent.add(this);
}
public PersonTreeNode(PersonTreeNode<Persona> parent,Persona data, LinkedList<PersonTreeNode<Persona>> children, boolean open,Integer pos) {
super(data, children);
this.setOpen(open);
parent.setLeaf(false);
if (pos==null || parent.getChildren().size()==0 )
parent.add(this);
else
parent.getChildren().add(pos,this);
}
public PersonTreeNode(Persona data, LinkedList<PersonTreeNode<Persona>> children) {
super(data, children);
}
public PersonTreeNode(PersonTreeNode<Persona> parent,Persona data, LinkedList<PersonTreeNode<Persona>> children) {
super(data, children);
parent.setLeaf(false);
parent.add(this);
}
public PersonTreeNode(PersonTreeNode<Persona> parent,Persona data) {
super(data);
parent.setLeaf(false);
parent.add(this);
}
public PersonTreeNode(PersonTreeNode<Persona> parent,Persona data,boolean open) {
super(data);
parent.setLeaf(false);
parent.add(this);
this.setOpen(open);
}
public PersonTreeNode(Persona data) {
super(data);
}
public PersonTreeNode(Persona data,boolean open) {
super(data);
this.setOpen(open);
}
public boolean isOpen() {
return open;
}
public void setOpen(boolean open) {
this.open = open;
}
public boolean isLeaf() {
return leafNode;
}
public void setLeaf(boolean value) {
this.leafNode=value;
if ( value )
this.open=false;
}
}
package model;
import java.util.LinkedList;
import org.zkoss.bind.annotation.Init;
import org.zkoss.zul.DefaultTreeModel;
import org.zkoss.zul.TreeModel;
import org.zkoss.zul.TreeNode;
public class ViewModel {
private PersonTreeNode<Person> treeRoot=null;
private TreeModel<TreeNode<Person>> treeNodes=null;
public PersonTreeNode<Person> getTreeRoot() {
return treeRoot;
}
public void setTreeRoot(PersonTreeNode<Person> treeRoot) {
this.treeRoot = treeRoot;
}
public TreeModel<TreeNode<Person>> getTreeNodes() {
return this.treeNodes;
}
public void setTreeNodes(TreeModel<TreeNode<Person>> treeNodes) {
this.treeNodes = treeNodes;
}
@Init
public void init(){
this.loadDati();
}
public PersonTreeNode<Person>addTreeNode(boolean open)
{
return this.addTreeNode( null, open);
}
public PersonTreeNode<Person> addTreeNode()
{
return this.addTreeNode( null, false);
}
public PersonTreeNode<Person> addTreeNode(PersonTreeNode<Person> parent)
{
return this.addTreeNode(parent, false);
}
public PersonTreeNode<Person> addTreeNode(PersonTreeNode<Person> parent,boolean open)
{
return this.addTreeNode(parent,open,null);
}
public PersonTreeNode<Person> addTreeNode(PersonTreeNode<Person> parent,boolean open,Integer pos)
{
if ( parent==null )
{
if ( this.treeRoot==null )
{
this.treeRoot=new PersonTreeNode<Person>(null,new LinkedList<PersonTreeNode<Person>>(),open);
this.treeNodes=new DefaultTreeModel<Person>(this.treeRoot);
}
parent=this.treeRoot;
}
Person row =new Person();
PersonTreeNode<Person> treeNode=null;
treeNode=new PersonTreeNode<Person>(parent,row,new LinkedList<PersonTreeNode<Person>>(),open,pos);
if ( treeNode.isOpen() )
((DefaultTreeModel<Person>)treeNodes).addOpenObject(treeNode);
return treeNode;
}
public void loadDati()
{
Person row=null;
PersonTreeNode<Person> nodeParent;
PersonTreeNode<Person> node;
nodeParent=this.addTreeNode(true);
row=nodeParent.getData();
row.setLastName("Bianchi");
row.setName("Gino");
node=this.addTreeNode(nodeParent,true);
node.setLeaf(true);
row=node.getData();
row.setLastName("Rossi");
row.setName("Nino");
node=this.addTreeNode(nodeParent,true);
node.setLeaf(true);
row=node.getData();
row.setLastName("Verdi");
row.setName("Paolo");
node=this.addTreeNode(nodeParent,true);
node.setLeaf(true);
row=node.getData();
row.setLastName("Blues");
row.setName("Ugo");
node=this.addTreeNode(nodeParent,true);
node.setLeaf(true);
row=node.getData();
row.setLastName("Bianchio");
row.setName("Gianni");
}
}
package model;
public class Person {
private String name;
private String lastName;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
} }
The basic principle is: when you use a model for a component, you should manipulate the component with the model.
A component renders its appearance upon its model (if exists). If you just open a Treeitem
with Treeitem.setOpen(true)
, it doesn't change the status in the model. So the node is still closed in the model. +
That's the reason the switching pages doesn't work as expected.
Thanks hawk, but i manipulate the state of the component opening with the model through <treeitem open="@bind(each.open)">, in my example the component is fully manipulated with the model. The problem is that in ZK8 the opening state is only manipulated by the DefaultTreeModel and not from my model. For me is not correct. I prefer the behavior zk 7.6 :-). Now'll use your SOLUTION, but I don't know if it will work the NotifyChange of the open status.
Ok Hawk, in this example i don't need @NotifyChange, but if I want to change to a run-time property of the tree through the model without reloading and rendering the whole tree must not do NotifyChange?
LuigiFabbri ( 2016-04-15 09:38:32 +0800 )editExample 1: I have a row button and on the button click event I want to change the value of a cell, i make notifychange of the value property . In this case i render only the treecell and not whole tree.
LuigiFabbri ( 2016-04-27 09:28:22 +0800 )editExample 2: I have a row button and on the button click event I want expand the child nodes, i make notifychange of the treeitem open property. In this case i render only the child nodes and not whole tree.
LuigiFabbri ( 2016-04-27 09:33:49 +0800 )editBEST SOLUTION
<zk>
<window width="100%" border="none" apply="org.zkoss.bind.BindComposer" viewmodel="@id('vm') @init('model.ViewModel')">
<tree model="@bind(vm.treeNodes)" mold="paging" pagesize="4">
<treecols sizable="true">
<treecol label="nome" width="120px"/>
<treecol label="cognome" width="300px"/>
</treecols>
<template name="model">
<treeitem open="@bind(each.open)">
<treerow>
<treecell label="@bind(each.data.name)"></treecell>
<treecell label="@bind(each.data.lastName)"></treecell>
<treecell>
</treecell>
</treerow>
</treeitem>
</template>
</tree>
</window>
</zk>
package model;
import java.util.LinkedList;
import org.zkoss.bind.annotation.Init;
import org.zkoss.zul.DefaultTreeModel;
import org.zkoss.zul.TreeModel;
import org.zkoss.zul.TreeNode;
public class ViewModel {
private PersonTreeNode<person> treeRoot=null;
private TreeModel<treenode<person>> treeNodes=null;
public PersonTreeNode<person> getTreeRoot() {
return treeRoot;
}
public void setTreeRoot(PersonTreeNode<person> treeRoot) {
this.treeRoot = treeRoot;
}
public TreeModel<treenode<person>> getTreeNodes() {
return this.treeNodes;
}
public void setTreeNodes(TreeModel<treenode<person>> treeNodes) { this.treeNodes = treeNodes; }
@Init
public void init(){
this.loadDati();
}
public PersonTreeNode<person>addTreeNode(boolean open){
return this.addTreeNode( null, open);
}
public PersonTreeNode<person> addTreeNode(){
return this.addTreeNode( null, false);
}
public PersonTreeNode<person> addTreeNode(PersonTreeNode<person> parent){
return this.addTreeNode(parent, false);
}
public PersonTreeNode<person> addTreeNode(PersonTreeNode<person> parent,boolean open){
return this.addTreeNode(parent,open,null);
}
public PersonTreeNode<person> addTreeNode(PersonTreeNode<person> parent,boolean open,Integer pos){
if ( parent==null )
{
if ( this.treeRoot==null )
{
this.treeRoot=new PersonTreeNode<Person>(null,new LinkedList<PersonTreeNode<Person>>(),treeNodes,open);
this.treeNodes=new DefaultTreeModel<Person>(this.treeRoot);
}
parent=this.treeRoot;
}
Person row =new Person();
PersonTreeNode<Person> treeNode=null;
treeNode=new PersonTreeNode<Person>(parent,row,new LinkedList<PersonTreeNode<Person>>(),this.treeNodes,open,pos);
if ( treeNode.isOpen() )
((DefaultTreeModel<Person>)treeNodes).addOpenObject(treeNode);
return treeNode;
}
public void loadDati(){
Person row=null;
PersonTreeNode<Person> nodeParent;
PersonTreeNode<Person> node;
nodeParent=this.addTreeNode(true);
row=nodeParent.getData();
row.setLastName("Bianchi");
row.setName("Gino");
node=this.addTreeNode(nodeParent,true);
node.setLeaf(true);
row=node.getData();
row.setLastName("Rossi");
row.setName("Nino");
node=this.addTreeNode(nodeParent,true);
node.setLeaf(true);
row=node.getData();
row.setLastName("Verdi");
row.setName("Paolo");
node=this.addTreeNode(nodeParent,true);
node.setLeaf(true);
row=node.getData();
row.setLastName("Blues");
row.setName("Ugo");
node=this.addTreeNode(nodeParent,true);
node.setLeaf(true);
row=node.getData();
row.setLastName("Bianchio");
row.setName("Gianni");
}
}
package model;
import java.util.LinkedList;
import org.zkoss.poi.ss.formula.functions.T;
import org.zkoss.zul.DefaultTreeModel;
import org.zkoss.zul.DefaultTreeNode;
import org.zkoss.zul.TreeModel;
import org.zkoss.zul.TreeNode;
public class PersonTreeNode<t> extends DefaultTreeNode<t> {
private static final long serialVersionUID = -8085873079938209759L;
// Node Control the default open
private boolean open = false;
private boolean leafNode=true;
private TreeModel<treenode<t>> treeNodes=null;
public PersonTreeNode(T data, LinkedList<persontreenode<t>> children,
TreeModel<treenode<t>>treeNodes,boolean open) {
super(data, children);
this.treeNodes=treeNodes;
this.open = open;
}
public PersonTreeNode(PersonTreeNode<t> parent,T data, LinkedList<persontreenode<t>> children,TreeModel<treenode<t>>treeNodes, boolean open) {
super(data, children);
this.treeNodes=treeNodes;
this.open = open;
parent.setLeaf(false);
parent.add(this);
}
public PersonTreeNode(PersonTreeNode<t> parent,T data, LinkedList<persontreenode<t>> children, TreeModel<treenode<t>>treeNodes,boolean open,Integer pos) {
super(data, children);
this.treeNodes=treeNodes;
this.open = open;
parent.setLeaf(false);
if (pos==null || parent.getChildren().size()==0 )
parent.add(this);
else
parent.getChildren().add(pos,this);
}
public PersonTreeNode(T data, LinkedList<persontreenode<t>> children,TreeModel<treenode<t>>treeNodes) {
super(data, children);
this.treeNodes=treeNodes;
}
public PersonTreeNode(PersonTreeNode<t> parent,T data, LinkedList<persontreenode<t>> children,TreeModel<treenode<t>>treeNodes) {
super(data, children);
this.treeNodes=treeNodes;
parent.setLeaf(false);
parent.add(this);
}
public PersonTreeNode(PersonTreeNode<t> parent,T data,TreeModel<treenode<t>>treeNodes) {
super(data);
parent.setLeaf(false);
parent.add(this);
}
public PersonTreeNode(PersonTreeNode<t> parent,T data,TreeModel<treenode<t>>treeNodes,boolean open) {
super(data);
parent.setLeaf(false);
parent.add(this);
this.treeNodes=treeNodes;
this.open = open;
}
public PersonTreeNode(T data,TreeModel<treenode<t>>treeNodes) {
super(data);
this.treeNodes=treeNodes;
}
public PersonTreeNode(T data,TreeModel<treenode<t>>treeNodes,boolean open) {
super(data);
this.treeNodes=treeNodes;
this.open = open;
}
public boolean isOpen() {
return open;
}
public void setOpen(boolean open) {
this.open = open;
if ( open )
((DefaultTreeModel<T>)treeNodes).addOpenObject(this);
else
((DefaultTreeModel<T>)treeNodes).removeOpenObject(this);
}
public boolean isLeaf() {
return leafNode;
}
public void setLeaf(boolean value) {
this.leafNode=value;
if ( value )
this.open=false;
}
}
Asked: 2016-02-22 14:25:11 +0800
Seen: 129 times
Last updated: May 18 '16
multiple selection with tree by mvvm
Databinding and auto-complete on combobox
Composite component and bind in ZK 6
How to detach / reattach MVVM windows?
Is there a way to resolve view model properties as input to client side javascripts?
How can I synchronize data in a ListBox in MVVM ? [closed]
MVVM Validator: class not found ? [closed]
How to Call Child ViewModel Method from Parent Window? [closed]
Uhmm weird: the next page button does not work unless you FIRST collapse the root node "Gino Bianchi" -> then you are able to go to page 2 where there is a row (but it is empty)... digging
gganassin ( 2016-03-04 12:03:20 +0800 )editExactly! :-)
LuigiFabbri ( 2016-03-22 14:42:04 +0800 )edit