Using Vaadin 7.4.9 - How to delete data from the grid

∥☆過路亽.° 提交于 2019-12-01 13:41:08

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!