Question

I have three Tabs and in each tab, I have a Grid.

The data for each Grid is coming from a database, so I am using rowRenderer to populate the Grids. The following code is common for all three Grids:

<grid id="myGrid1" width="950px" sizedByContent="true" rowRenderer="com.example.renderer.MyRowRenderer">

The rows are constructed from Doublebox objects. The data is populated successfully.

The Problem:

I need to handle multiple-cell editing on the client side. The editing is done via mouse-clicking on a particular cell and entering a value.

As example let's say that the user edits first cell on the first row and the value should be propagated to all other cells on the same row and in all three Grids (so also the two Grids which the user currently does not see, because they are in tabpanes). I am using jQuery to do this value propagation and it works OK.

I am passing the jQuery as follows:

doublebox.setWidgetListener(Events.ON_CHANGING, jQuerySelectors);
doublebox.setWidgetListener(Events.ON_CHANGE, jQuerySelectors);

This makes it possible to change the value in 1 cell and the change is instantly (visually) seen in all other cells filtered by jQuery selectors.

The problem is that the value is visually distributed to all the cells, but when I try to save the Grid data back to the database, the background values are the old ones. I am assuming that ZK-Grid component is not aware that jQuery changed all the cell values. Nevertheless if I manually click on a cell that already has the NEW value (enter/leave/change focus) when I save the grid the NEW value is correct in that particular cell. Maybe that's a hint how can I resolve this.

Code of how I extract the Grid values:

Grid tGrid = (Grid) event.getTarget().getFellow("myGrid1");
ListModel model = tGrid.getModel();
MyCustomRow tRow = (MyCustomRow)model.getElementAt(i); 

The model for my Grid is a List of MyCustomRow:

myGrid1.setModel(new ListModelList(List<MyCustomRow> populatedList));

I have a couple of assumptions, but whatever I have tried, hasn't worked. I have in mind that jQuery events and ZK-Events are different and probably isolated in different contexts. (Although I have tried to fire events from jQuery and so on..)

Do you have any suggestions? As a whole is my approach correct or there's another way to do this? Thanks for your time in advance!

Was it helpful?

Solution

Your problem is exactly what you are expecting.
Zk has it's own event system and do not care about your jq,
cos it's jq and zk don't observ the DOM.

The ways to solve your problem.

  1. Use the "ZK-Way":
    Simply listen at server-side and chage things there.
    I am not sure if not selected Tabs
    are updateable, but I am sure you could update the Grid
    components on the select event of the Tab.

  2. Fire an zk-event your self:
    All you need to know, is written in the zk doc.
    Basically, you collect your data at client side, send
    an Event to the server via zAu.send() extract the
    data from the json object at serverside and update your Grids

I would prefer the first one, cos it's less work and there should not be
a notable difference in traffic.

OTHER TIPS

I post the solution we came up with:

This is the javascript attached to each Doublebox in the Z-Grid

//getting the value of the clicked cell
var currVal = jq(this).val(); 

//getting the next cell (on the right of the clicked cell)
objCells = jq(this).parents('td').next().find('.z-doublebox');

// if there's a next cell (returned array has length) - set the value and
// fire ZK onChange Event
if (objCells.length) {
    zk.Widget.$(jq(objCells).attr('id')).setValue(currVal);
    zk.Widget.$(jq(objCells).attr('id')).fireOnChange();
} else {  //otherwise we assume this is the last cell of the current tab
    //So we get the current row, because we want to edit the cells in the same row in the next tabs
    var currRow = jq(this).parents('tr').prevAll().length;

    //finding the next cell, on the same row in the hidden tab and applying the same logic
    objCellsHiddenTabs = jq(this).parents('.z-tabpanel').next().find('.z-row:eq(' + currRow + ')').find('.z-doublebox');
    if (objCellsHiddenTabs.length) {
        zk.Widget.$(jq(objCellsHiddenTabs).attr('id')).setValue(currVal);
        zk.Widget.$(jq(objCellsHiddenTabs).attr('id')).fireOnChange();
    }
}

The java code in the RowRenderer class looks something like this:

... 
if (someBean != null) {

      binder.bindBean("tBean", someBean);

      Doublebox box = new Doublebox();
      setDefaultStyle(box);
      row.appendChild(box);
      binder.addBinding(box, "value", "tBean.someSetter");
 ...

 private void setDefaultStyle(Doublebox box) {
    box.setFormat("#.00");
    box.setConstraint("no negative,no empty");
    box.setWidth("50px");

    String customJS = ""; //the JS above

    //this is used to visually see that you're editing multiple cells at once
    String customJSNoFireOnChange = "jq(this).parents('td').nextAll().find('.z-doublebox').val(jq(this).val());";
    box.setWidgetListener(Events.ON_CHANGING, customJSNoFireOnChange);
    box.setWidgetListener(Events.ON_CHANGE, customJS);

}

What is interesting to notice is that ZK optimizes this fireOnChange Events and send only 1 ajax request to the server containing the updates to the necessary cells.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top