I have implemented a load on demand tree by extending AbstractTreeModel. Once I have opened a branch node, and then I do some action to update the data behind that branch, it is not updating the UI to reflect the changes (something added or deleted in the branch). I have to refresh the whole tree to be able to see the updated data. This update to the tree causes all opened branches to collapse again.
Can someone point me to where there is an example, or explain to me how I can get branch nodes to update once they have been populated in the tree but the underlying data has changed and I need to update the UI to reflect that.
Added information as per request...
Portion of zul with tree:
DMSTreeModel which extends AbstractTreeModel. In the updateTree method I just have some hard coded stuff to get the path. At this point I only add items to this location in the tree to see if I can get the UI to update. Once I have it working I will modify code to figure out what the path is for other scenarios.
I added the requested code to the original message. I have played around with various things but still unable to get the postNotifyChange to do anything.
You can use either model.fireEvent(TreeDataEvent.INTERVAL_ADDED, model.getPath(selectedItem) , index, index) or @NotifyChange("model") to update the tree in a browser. But first way has better performance.
Notice that fireEvent()'s 2nd parameter is the path of newly-added node's parent node, you can get a node's path with AbstractTreeModel.getPath().
Here is a simple example to demonstrate the idea:
<div apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('support.component.tree.TreeEventVM')">
<button onClick="@command('add')">add</button>
<tree model="@bind(vm.model)" selectedItem="@save(vm.selectedItem)">
<template name="model">
<treeitem>
<treerow>
<treecell label="@load(each)"></treecell>
</treerow>
</treeitem>
</template>
</tree>
</div>
@Command
// @NotifyChange("model") simple but cost more effort for it renders the whole tree again
public void add(){
if (selectedItem != null){
MyNode newChild = new MyNode(Calendar.getInstance().getTime().toString());
selectedItem.getChildren().add(newChild);
int index = selectedItem.getChildren().indexOf(newChild);
//fire an event upon situations, please refer to TreeDataEvent for the complete list of tree data events
model.fireEvent(TreeDataEvent.INTERVAL_ADDED, model.getPath(selectedItem) , index, index);
// no effect for no binding on root
// BindUtils.postNotifyChange(null, null, model.getRoot(), "*");
}
}
When using a tree model, you should consider ZK's default tree model and node class first, then replace some of them with your own according to the complexity of your requirement.
DefaultTreeModel and DefaultTreeNode will fire events automatically for you. But implement your own tree model, you should fire events by yourselves.
This example helped me to sort out where I was going wrong. Once I started using INTERVALADDED instead of CONTENTSCHANGED then the tree would finally update. I also discovered that the ZK 6.5.2 that I was using had a defect that was causing the null pointer error to be thrown. 6.5.4 fixed that.
I tried this but it does not work. In MyTreeModel class, which extends AbtractTreeModel I have a command "updateTree" that calls postNotifyChange. I obtain "mineObject" by using this.getChild(path) path to the "folder" that its contents have changed. But no update occurs when called. Ideas?
I have tried fireEvent(ListDataEvent.CONTENTS_CHANGED,path, 0, 1); to no success. It produces a null pointer error deep within ZK. As for indexFrom and indexTo, I'm not exactly sure what this is asking for. I have played with all sorts of values. What exactly are these values?
maybe thsi is the reason : Fires a TreeDataEvent for all registered listener Note: you can invoke this method only in an event listener. are you in an eventlistener?
This makes no sense. The method call to fire the event has to live inside the listener of the event? I tried it but as suspected it never gets called because I have no way to trigger an event to cause the listener to be invoked and make this call to fire the event. Chicken/egg scenario. Code Sample?
MVC or MVVM?
chillworld ( 2015-02-13 06:27:31 +0800 )editMy application is using MVVM.
rwoolf ( 2015-02-13 16:50:12 +0800 )editshow me the zul and viewmodel (part where you change the object and part of the updatetree)
chillworld ( 2015-02-13 21:59:52 +0800 )editI added the requested code to the original message. I have played around with various things but still unable to get the postNotifyChange to do anything.
rwoolf ( 2015-02-17 23:13:26 +0800 )edit