Search code examples
vaadin-gridvaadin8

add dynamic row content to vaadin grid


In vaadin7, I used GeneratedPropertyContainer to do this, eg adding row number:

        wrappedContainer = new GeneratedPropertyContainer(_container);
        wrappedContainer.addGeneratedProperty("#", 
                new PropertyValueGenerator<Integer>() {

                    @Override
                    public Integer getValue(Item item, Object itemId, Object propertyId) {
                        return (int) _container.indexOfId(itemId) + 1;
                    }

                    @Override
                    public Class<Integer> getType() {
                        return java.lang.Integer.class;
                    }
                }
        );

        setContainerDataSource(wrappedContainer);

In vaadin8, since GeneratedPropertyContainer is deprecated, I tried to do like this: grid.addColumn((v)->((List)_container.getData().getItems()).indexOf(v)+1);

But the index is static, when I sort the rows ascending and descending, the row number is moving too.

What I need is the first row is row number 1 and the last row is row number N, no matter how I sort the rows.

Thanks.


Solution

  • Unfortunately, as far as I can tell there is no simple solution out of the box. However, you can do like the following code:

    Grid<MyBean> grid = new Grid<>();
    grid.setDataProvider(new RowIndexDataProviderWrapper<>(DataProvider.ofItems(new MyBean("Item 1"), new MyBean("Item 2"), new MyBean("Item 3"))));
    grid.addColumn(MyBean::getRowIndex).setCaption("#");
    grid.addColumn(MyBean::getName).setCaption("Name");
    
    public interface RowIndexAware {
        void setRowIndex(int rowIndex);
        int getRowIndex();
    }
    
    public class MyBean implements RowIndexAware {
        // implement the interface (e.g. store row index in field)
        // and add your bean properties
    }
    
    public class RowIndexDataProviderWrapper<T extends RowIndexAware, F> implements DataProvider<T, F> {
    
        private DataProvider<T, F> wrapped;
    
        public RowIndexDataProviderWrapper(DataProvider<T, F> wrapped) {
            this.wrapped = wrapped;
        }
    
        // delegate all methods to be implemented for DataProvider interface
        // to wrapped DataProvider with the exception of "fetch":
    
        @Override
        public Stream<T> fetch(Query<T, F> query) {
            List<T> result = wrapped.fetch(query).collect(Collectors.toCollection(ArrayList::new));
            for (int i = 0; i < result.size(); i++) {
                result.get(i).setRowIndex(query.getOffset() + i);
            }
            return result.stream();
        }
    
    }
    

    The idea is to get the row index when rows are fetched within the DataProvider and to store them in your bean.