Table not recalling CellStyleGenerator even when requestRepaint() is called

Hello,

I have a problem, which seems to be present as well in the
Table, row styling
example for a Table: When the background information about the item in the table is changed (in the example by double-clicking on a table cell), the item’s property is updated, but the table
does not
reflect the new state.

In the example I either have to switch the table to editable and back, or I have to scroll the cell in question out and back in again.

Although the example code states:


        // this causes the CellStyleGenerator to return new styles,
                    // but table can't automatically know, we must tell it:
                    table.requestRepaint();

the table does not refresh and does not call new values from the CellStyleGenerator.

I have the same problem in my app: The items in the table have a boolean property which is bound to a CheckBox and a text string. The table is editable; when clicking the checkbox, the corresponding property is set in the item (I debugged that), and in the ValueChangeListener for the checkbox I call table.requestRepaint(). But no new calls to the CellStyleGenerator.

I tried the example with Safari/Firefox on Mac OSX and with Firefox/IE on Win XP, it did not work in any of these.

Shouldn’t requestRepaint() be sufficient to force a reload of the cell styles?

greetings
Peter

That’s funny, I have exactly the same problem right now. I wonder if that’s a regression or if it never worked?
My case: I have a dialog allowing to set background color on some cells, depending on their content. So I need to refresh the current content.
I use requestRepaint(), and even disableContentRefreshing() before the update of the table data, and enableContentRefreshing(true) after, but nothing happens (although I think the disable/enable pair worked at one point). I have to scroll forth and back to see the update.

One thing potentially problematic here is the nature of Web applications. Unless Vaadin made special measures for that (like a Comet channel or server polling), the server cannot push updates to the client. So, somehow, I think such refresh can happen only upon user action (or JavaScript timer or similar).
It is not a major problem as the change happens after validation of a form, so user interaction is here, but it just doesn’t work.

It’s right that the server can’t push, but as I have set the checkbox to immediate a click results in a Ajax call to the server, which ends up in my ValueChanged-Handler where I call table.requestRepaint(). So it should be possible to pass this repaint request in the answer of the Ajax-call back to the client where it could be evaluated and should lead to a further refresh request for the table.

Yes, as I wrote, it isn’t a problem when the refresh is done upon user interaction, and I think it used to work, as it is done in the demo. It just no longer works… :frowning:

It is an issue that was introduced in Vaadin 6.7 when partial repainting of the Table was added. The Table now only repaints the rows / contents when something changes that affects the contents. Previously the rows were always repainted, causing a lot of flickering and other issues.

There is a ticket for this: http://dev.vaadin.com/ticket/7790

The workaround at the moment is to call some method that affects the rows, e.g. table.setCellStyleGenerator(table.getCellStyleGenerator());

Thanks a lot Artur, for the info.

I will test your solution on monday, when I’m back in the office. I thought of a different thing to try: For every property of the item that is changed I would call setValue(getValue()); if this redraws the column rows that would be enough, as I don’t need to redraw the whole table, only one row. Although I don’t know if the cell styles are regenerated then.

I’ll try these things on monday and post the results here.

greetings
Peter

Ok, I got it working with this call, but had some little problems. Let me summarize:

I have a table backed by items which have one Boolean property (this is a
mark for deletion
flag the user can check). The boolean property is displayed in the - editable - table by a checkbox, the rest of the item properties are strings which are not editable and are just displayed as text.

I have a CellStyleGenerator attached to the table because I want the items that have the property set to true be displayed with the css attribute
text-decoration: line-through
.

In the value-change-listener for the checkbox I now set the value into my property, after that I call table.setCellStyleGenerator(table.getCellStyleGenerator()) and table.requestRepaint().


But:
As it turns out, both setting the property and setting the CellStyleGenerator result in a recursive call of the value-change-listener and so lead out-of-memory heap crash.

What I did, is guard the entrance to the listener code with a boolean variable (code excerpt):


             checkBox.addListener(new ValueChangeListener() {
                        public void valueChange(ValueChangeEvent event) {
                            if (!processingDeletedValueChange) {
                                processingDeletedValueChange = true;
                                personsFound.switchMarkDeleted(itemId, newValue);
                                table.setCellStyleGenerator(table.getCellStyleGenerator());
                                table.requestRepaint();
                                processingDeletedValueChange = false;
                            }
                        }
                    });

Looks ugly, but it works.

If somebody comes up with a better solution…

It works. Almost…
It doesn’t work if I have not scrolled the table yet. It works if I scroll first, then apply the style changes. Except that the first, partially displayed row isn’t updated… And sometime, it just doesn’t work.
In short, a useful, but not perfect workaround. I hope the fix will come soon! :slight_smile:

Looking at the ticket, it looks like the fix is in 6.7.2 but the issue doesn’t seem to be fixed for me with 6.7.2. If I switch back to 6.6.5 it works for me.

My table has a single generated column containing a Label with HTML data. I use action to edit an entry, save the item and set the value in the table to select it back. My table doesn’t have scrollbar for the example I am testing

6.7.2 didn’t change anything for me.
Perhaps my problem is that I don’t use CellStyleGenerator, but my Property sub-class is a CssLayout where I have Label components, and I override getCss() to define the style of each Label (see
Representing tri-dimensional data in a grid
for details; I can make a quick demo if you need a test env.).
I expected with this fix that requestRepaint() would do a full refresh (generation) of the table, but that’s still not the case.

Try subclassing the table, and calling the protected Table#refreshRenderedCells(); - that’s pretty much what table.setCellStyleGenerator(table.getCellStyleGenerator()); does.

It might be worth a go…

Hello - Is there going to be a fix for this? It doesn’t work with 6.7.2 or 6.7.3 and I don’t want to have to go through all my applications and sub-class Tables. I am stuck on 6.6.5 because of that. I am ok if it will be part of Vaadin 7, just need to know if a reasonable fix/workaround will be planned…

Hi!
I had the same kind of problem since the 6.7 versions, even with the workaround or the 6.7.2 version.

I wanted to be able to change some row style depending on the selected one. In order to do so I had to create a new CellStyleGenerator in the valueChange method.
It worked perfectly with the 6.6 version.

Here is the way I managed the problem : subclass Table to be able to call the Table#enableContentRefreshing(boolean refreshContent); method.


@Override
public void valueChange(ValueChangeEvent event) {
	
	// Get some data that will determine which row will have a certain style

	table.setCellStyleGenerator(new Table.CellStyleGenerator() {
		
		@Override
		public String getStyle(Object itemId, Object propertyId) {
			if ( [i]
I don't care about this property
[/i] ) {
				return null;
			}
			
			if ( [i]
there's something about the data I got earlier
[/i] ) {
				return "style_1";
			}
			if ( [i]
there's something else about the same data
[/i] ) {
				return "style_2";
			}

			return null;
		}
	});

	[b]
table.enableContentRefreshing(true);
[/b]

}

It now works fine, but may not be the best way to do it. If someone has a suggestion please let me know !
Thanks !!

I tried table sub-classing as well and it is not working for me. Can you tell what I am doing wrong?


class MapActionsTable extends Table {

	/**
	 * 
	 */
	private static final long serialVersionUID = 7409708072000701247L;
	
	@Override
	protected void enableContentRefreshing(boolean refreshContent) {
		super.enableContentRefreshing(refreshContent);
	}
}

MapActionsTable actionsList;

actionsList = new MapActionsTable();
actionsList.setImmediate(true);
actionsList.setSelectable(true);

		actionsList.addGeneratedColumn("function_detail", new Table.ColumnGenerator() {
			/**
			 * 
			 */
			private static final long serialVersionUID = -244015637085210622L;

			public Component generateCell(Table source, Object itemId, Object columnId) {
				/* Since we use BeanItemContainer, itemId is pojo/bean itself */
				Function act = (Function) itemId;
				Label l = new Label();
				l.setValue(act.getFunction_detail());
				l.setContentMode(Label.CONTENT_XHTML);
				/*
				 * setSizeUndefined is required for some reason, without it the content is cut off without wrapping and the
				 * column size is small
				 */
				l.setSizeUndefined();
				return l;
			}
		});
		actionsList.enableContentRefreshing(true);
		actionsList.setWidth(100, UNITS_PERCENTAGE);
		actionsList.setPageLength(5);
		actionsList.setContainerDataSource(actionsCont);
		actionsList.setVisibleColumns(new Object[] { "function_detail" });
		actionsList.setColumnHeader("function_detail", "Actions");

That is the set up. After that when the bean item changes for a row, the generated column function_detail doesn’t refresh visually. It refreshes fine even without enableContentRefreshing with 6.6.5

I was finally able to figure out the magic formula.

I did not need to subclass. All I had to do was call this when the data update happened

if (source == save) {
			action = (Function) actionsList.getValue();
			updateAction(action);
			/*
			 * As of Vaadin 6.7, we need to specifically refresh row cache if table has generated column and underlying data 
			 * changed.
			 * 
			 * https://vaadin.com/forum/-/message_boards/view_message/1295543
			 * 
			 * http://dev.vaadin.com/ticket/7790
			 */
			[color=#fc0101]
actionsList.refreshRowCache();
[/color]
		}

I’m curious to know if you ran into any issues with using refreshRowCache(). I’m working on a project where we’re trying to do something very similar. We have a generated column of Checkboxes to select items in the table. In the valueChange listener, I’m updating a list of selected IDs and calling select() on the table. The original problem I was having was the CSS styling for the table row wasn’t being updated, but adding in a call to refreshRowCache() fixed that. The problem now, though, is if you click the checkboxes very fast and there’s any lag time at all with the server, the valueChange logic and refresh cause the clicks that occur while the code is executing to be ignored. So I can click down the list of checkboxes and usually only every other one is selected due to the timing issue. Did you ever run into any issues like this?

(I’ve also tried using markAsDirtyRecursive and setCellStyleGenerator, both of which refresh the table, but both also have the same issue of losing clicks).