0

Understanding updates to Grid model

asked 2012-10-24 02:39:27 +0800

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

updated 2012-10-24 02:47:36 +0800

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");

     b.addEventListener("onClick", new EventListener<Event>(){
      private Calendar  cal = Calendar.getInstance();

      @Override
      public void onEvent(Event event) throws Exception {
         ..... cal.setTheCalender........
          
    
          ((SomeListModelMap) g.getModel()).updateMap(cal);
        
      } } );
  }
}


--Brad

delete flag offensive retag edit

7 Replies

Sort by ยป oldest newest

answered 2012-10-24 03:01:04 +0800

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

The javadocs for ListModelMap say

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"...

--Brad

link publish delete flag offensive edit

answered 2012-10-24 03:38:50 +0800

jj gravatar image 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.

link publish delete flag offensive edit

answered 2012-10-24 05:19:32 +0800

kbsimm gravatar image 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.

link publish delete flag offensive edit

answered 2012-10-24 12:03:04 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

updated 2012-10-24 12:04:20 +0800

please make a try with

grid.invalidate();
instead of the second
setModel()

sometimes i have the same problems.

link publish delete flag offensive edit

answered 2012-10-24 15:31:35 +0800

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

Thank you for the help.

grid.invalidate() did not help.

The javadocs say the following about invalidate

 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?

link publish delete flag offensive edit

answered 2012-10-24 16:01:01 +0800

gekkio gravatar image gekkio flag of Finland
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

link publish delete flag offensive edit

answered 2012-10-24 18:25:15 +0800

kbsimm gravatar image 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....

--Brad

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-10-24 02:39:27 +0800

Seen: 111 times

Last updated: Oct 24 '12

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