I need to delete data from the grid (container) and then i need refresh the rows. How I can do it?
Grid grid = new Grid();
IndexedContainer container = new I
Your Caused by: java.lang.StackOverflowError
problem is because you're changing values inside a ValueChangeListener
, which generates other events, and you end up in an endless loop, as @Manuel Kollegger was trying to point out, so a different approach is required.
The simplest idea which came to mind, is to have a generated column, for which you calculate the value based on the other 2. However, as per the docs, there's no direct way in Vaadin 7 to define a generated column, so you have to wrap your container with a GeneratedPropertyContainer
:
Grid has no generated columns. Instead, the container data source can be wrapped around a
GeneratedPropertyContainer
.
Also, you may wish to make the generate property read-only, to prevent the user from manually editing it.
The example below, based on your description, shows how this is done. Please note that for the sake of brevity, it's not entirely fool-proof (nulls, invalid values, etc), but it should get you started:
import com.vaadin.data.Item;
import com.vaadin.data.util.GeneratedPropertyContainer;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.data.util.PropertyValueGenerator;
import com.vaadin.ui.Grid;
import com.vaadin.ui.VerticalLayout;
import java.util.Random;
public class GridWithCalculatedColumn extends VerticalLayout {
public GridWithCalculatedColumn() {
// indexed container allowing the definition of custom properties
IndexedContainer container = new IndexedContainer();
container.addContainerProperty("firstNumber", Integer.class, 0);
container.addContainerProperty("secondNumber", Integer.class, 0);
// generated property container allowing the definition of generated properties
GeneratedPropertyContainer wrappingContainer = new GeneratedPropertyContainer(container);
wrappingContainer.addGeneratedProperty("sum", new PropertyValueGenerator<Integer>() {
@Override
public Integer getValue(Item item, Object itemId, Object propertyId) {
// sum the other 2 columns
// NOTE: for the sake of simplicity this does not handle invalid values such as "null"
return (Integer) item.getItemProperty("firstNumber").getValue() + (Integer) item.getItemProperty("secondNumber").getValue();
}
@Override
public Class<Integer> getType() {
return Integer.class;
}
});
// add some dummy data
Random random = new Random();
for (int i = 0; i < 5; i++) {
Item item = wrappingContainer.addItem(i);
item.getItemProperty("firstNumber").setValue(random.nextInt(10));
item.getItemProperty("secondNumber").setValue(random.nextInt(10));
}
// basic grid setup
Grid grid = new Grid();
grid.setContainerDataSource(wrappingContainer);
grid.setEditorEnabled(true);
// disable editing of the "calculated value"
grid.getColumn("sum").setEditable(false);
addComponent(grid);
}
}
Result:
Using Vaadin 7.4.9 is very tedious when it comes to Grids.
Removing items has to be done using container.removeItem(item)
.
Additionally refreshing a Grid is easy in Vaadin 7.7 (method addition of refreshAll
and refreshRow()
) and especially easy in Vaadin 8 (using events and a Dataprovider).
In Vaadin 7 you will have to hack it a bit by calling clearSortOrder
which automatically redraws the grid.
The following code is used when you update the UI from another Thread (i.e. not in a ValueChangeListener) however you need to enable the Vaadin-Push Addon which is a separate dependency.
getUI.access(() -> {
List<SortOrder> sortOrders = new ArrayList<>();
grid.getSortOrder().forEach(sortOrder -> sortOrders.add(sortOrder));
grid.recalculateColumnWidths();
grid.clearSortOrder();
grid.setSortOrder(sortOrders);
getUI().push();
});
Edit: If you do the deletion with a buttonClick or ValueChangeEvent of a combobox you can simply do:
component.addValueChangeListener(e -> {
Item item = container.getItem(35);
container.removeItem(item);
container.addItem(35);
item.getItemProperty("Person5").setValue("SS");
grid.recalculateColumnWidths();
grid.clearSortOrder();
grid.refreshAllRows();
});
However be careful, your implementation has a ValueChangeListener on the container which calls container.removeItem(35)
this will result in another trigger another ValueChanged-Event which will try to remove item number 35 again. You have to use another component for the ValueChangeListener otherwise you run into an endless cycle