# Understanding updates to Grid model

kbsimm
153
http://www.ArivX.com/

We have a grid with an extended ListModelMap and an extended RowRenderer. And we have a component that has buttons that when pressed will change the ListModelMap and thus we want it to update the grid.
We have reviewed http://www.zkoss.org/zkdemo/grid/dynamic_data and http://books.zkoss.org/wiki/ZK%20Developer%27s%20Reference/MVVM/Syntax/ViewModel/@NotifyChange

When the button is pushed we call the method to update the ListModelMap. We have logs to see the data change but our grid does not update. I expect that since the grids model has changed some sort of rerender event would be fired and the CustomerRowRenderer would run again.

Is the Map not bound to the grid simply by setting this map as the map for this grid? Do I need @NotifyChange and/or other annotations?

Here is some sudo code...(Everything we do is in java... no zul)

Calender calendar = Calender.getInstance();
Grid g = new Grid()
SomeCustomHashMap hashMap = new SomeCustomerHashMap(calendar)
CustomerListModelMap m = new ListModelMap(hashMap)
CustomRowRender r = new CustomerRowRenderer();

g.setModel(m);
g.setRowRenderer(r);

SomeControlWithButtons ctrl = new SomeControlWithButtons(g);

g.setParent(win);
ctrl.setParent(win);



SomeCustomHashMap.java

public class SomeCustomHashMap extends HashMap
{
public SomeCustomHashMap(Calendar cal)
{
update(cal)
}

public void update(Calender cal)
{
....goGetTheData.......
for (.... theData...)
{
this.put(theDataKey, theDataValue);
}
}
}


CustomListModelMap.java

public class CustomListModelMap extends ListModelMap
{
CustomListModelMap _m;
public CustomListModelMap(SomeCustomHashMap m)
{
super(m, true);
_m = m;
.....doSomeOtherStuf.....
}

public void updateMap(Calendar cal)
{
_m.update(cal);
}
}


SomeControlWithButtons.java

public class SomeControlWIthButtons extends Box
{
public SomeControlWithButtons(Grid g)
{
Button b = new Button("Yesterday");

private Calendar  cal = Calendar.getInstance();

@Override
public void onEvent(Event event) throws Exception {
..... cal.setTheCalender........

((SomeListModelMap) g.getModel()).updateMap(cal);

} } );
}
}


delete retag edit

## 7 Replies

kbsimm
153
http://www.ArivX.com/

Constructor Detail
ListModelMap

public ListModelMap(java.util.Map<K,V> map,
boolean live)

Constructor.

Parameters:
map - the map to represent
live - whether to have a 'live' ListModel on top of the specified map. If false, the content of the specified map is copied. If true, this object is a 'facade' of the specified map, i.e., when you add or remove items from this ListModelMap, the inner "live" map would be changed accordingly. However, it is not a good idea to modify map if it is passed to this method with live is true, since Listbox is not smart enough to hanle it. Instead, modify it thru this object.
Since:
2.4.0



So when called with live=true it should update.... although this "however" section here is a little worrisome... What does it mean "ListBox is not smart enough to handle it."? And what do they mean by modify it thru this object.... what do they mean by "thru" as one still has to update the hashMap and _m and m are the same animal.

I have also tried using a BindingListModelMap... although that seems like it used more for situations where the data is "paged"...

jj
638 3

I think the new Annotation binding will work, or traditionally, you want to call g.setModel(m) again after the button push.

kbsimm
153
http://www.ArivX.com/

I messed with the annotation bindings a bit and that didn't work. I am not sure I was doing them right. But to me the bindings don't seem necessary in this scenario as I would think the setModel would perform the binding.

Of course another call to setModel would work but that defeats the purpose of binding all together.

9393 3 7 16
http://www.oxitec.de/

grid.invalidate();
setModel()

sometimes i have the same problems.

kbsimm
153
http://www.ArivX.com/

Thank you for the help.

grid.invalidate() did not help.

 invalidate

public void invalidate()

Description copied from interface: Component
Invalidates this component by setting the dirty flag such that it will be redraw the whole content of this component and its dependences later. And, the widget associated with this component and all its descendant at the client will be deleted and recreated, too.

If the application is totally controlled by the server side (i.e., you don't write client codes), you rarely need to access this method.

It can be called only in the request-processing and event-processing phases. However, it is NOT allowed in the rendering phase.

Specified by:
invalidate in interface Component



Concerning the paragraph above which starts, "It the application is totally controlled by the server....". It is not clear what the author considers "server side" or "client code". As you know all of the code resides on the server and only composed html and javascript are sent to the client. Perhaps the author meant java code vs zul markup language?

gekkio
899 1
http://gekkio.fi/blog

You cannot modify the original map that you passed to the ListModel. The whole point of using a ListModel is that you must make all changes using methods on the ListModel if you want them to have an effect on the grid.

Examples with live=true

Map original = new HashMap();
ListModelMap listModel = new ListModelMap(original, true);

original.put(...) // Grid is NOT updated, because ListModel cannot know you have changed something
listModel.put(...) // Grid is updated, because you made the changes through ListModel

// The data structures are modified in both original and ListModel, because ListModel is just a view over the original map
// However, if you modify the original directly, ZK cannot detect changes


Examples with live=false
Map original = new HashMap();
ListModelMap listModel = new ListModelMap(original, false);

original.put(...) // ListModel will not be updated, and the grid will not be updated
listModel.put(...) // Grid is updated, because you made the changes through ListModel. Original is unchanged

// Original and ListModel are completely separate, because ListModel makes a copy of original
// Modifying the original will not modify ListModel, and the grid will not see any updates


kbsimm
153
http://www.ArivX.com/

I see..... thank you for the great explanation!

In my sample, I first thought, since I need to replace the whole hashMap, I might need to update CustomListModelMap.java as follows:

public class CustomListModelMap extends ListModelMap
{
CustomListModelMap _m;
public CustomListModelMap(SomeCustomHashMap m)
{
super(m, true);
_m = m;
.....doSomeOtherStuf.....
}

public void updateMap(Calendar cal)
{
_m.update(cal);
this.clear();
this.putAll(_m);
}
}


But I can't do that as the call to this.clear() will also clear _m. And not doing this.clear() the call to this.putAll(_m) will not remove any old key, value pairs that are not present in _m. I suppose I could clone _m, then clear, then putAll... yuck...

Unfortunately after all this I don't think I will use this method. Other details around the grid such as updating headers also need to be dealt with. Thus the complexity is getting a bit high. It looks like perhaps just rebuilding the entire grid may be a better solution. We will see....

Thank you all again....

[hide preview]