Table - How to dynamically change highlight color of selected row?

Most of the time, I’m fine with the default dark blue color that highlights a selected row in a Table. However, I am now trying to change the highlight color to, say, a shade of green instead of blue if the row has certain data in it.

I know how to use a ValueChangeListener to get the value of the row that was selected in the Table. I also know how to use a CellStyleGenerator to set the background color of each row. However, my problem is that the CellStyleGenerator is only called when Table is being rendered, and so the getStyle() method is never invoked when I click on various rows.

I tried calling refreshRowCache() from my ItemClickListener to force another call to getStyle() but the highlighted row is not affected by getStyle() - the highlighted row instead remains the same default color of dark blue.

Again, I want a row that has data that meets certain conditions to be highlighted in green when I click on it, and if the row does not meet those conditions, I want it to be highlighted in the default dark blue color.

Any ideas on what I can do?

Hi,

Good question. I had to try this out. I could just come up with a little hack at the moment, by adding an invisible column to the container:

final Table t = new Table();
t.addContainerProperty("first", String.class, null);
t.addContainerProperty("second", String.class, null);
t.addContainerProperty("invisible", String.class, null); // extra column
t.setVisibleColumns(new Object[] {"first", "second"});

// Then I added a ItemClickListener
t.addListener(new ItemClickEvent.ItemClickListener() {	
	public void itemClick(ItemClickEvent event) {
		// The trick here, would be to set the invisible column visible back and fort.
		// However, this is not seen in any way
		t.setVisibleColumns(new Object[] {"first", "second", "invisible"});

		// Check your requirements for hilighting the row
		if (requirementsMet()) {
			t.getItem(event.getItemId()).getItemProperty("invisible").setValue("colored"); // Here, I set the style name, that can be used in the CellStyleGenerator
		} else {
			t.getItem(event.getItemId()).getItemProperty("invisible").setValue(null); // Here, I remove the style name.
		}
		t.setVisibleColumns(new Object[] {"first", "second"});
	}	
});

// Finally, I add the CellStyleGenerator:
t.setCellStyleGenerator(new Table.CellStyleGenerator() {
	public String getStyle(Object itemId, Object propertyId) {
		if (propertyId == null) {
			// So, I'll now return our style stored in the invisible property.
			return (String) t.getItem(itemId).getItemProperty("invisible").getValue();
		}
		return null;
	}
});

And in the css file:

.v-table .v-selected.v-table-row-colored{
	background: green;
}

One drawback with this approach, is that the “colored” classnames are left until you reselect a row and the requirements aren’t met anymore. In this case, you would not notice, since it is the combination of .v-selected and .v-table-row-colored that hilights your row. By making sure that the style name is removed when selecting next time, you’ll be fine.

BR,
Johan

Hi Johan,

I tried the invisible column idea but had the following issues:

  1. This line was generating an exception, with a message suggesting I use addNestedContainerProperty() instead:
    transmissionTable.table.addContainerProperty(“invisible”, String.class, null);

Earlier in the code, I have this line:
transmissionTable.table.setContainerDataSource(beanContainer);

  1. I changed the line to:
    beanContainer.addNestedContainerProperty(“invisible”);

but then I got a NoSuchMethodException because Vaadin then tried to look for an “areInvisible()” method on the backing bean.

Thanks,
Paolo