How to cancel the vaadin grating?

I am trying to create a simple java application using Spring Boot and Vaadin. I need to add a table to the UI like this: https://www.screencast.com/t/1c4xkr4IE

It can be extended by periods.

It looks like the Vaadin Grid item suits my requirements perfectly, but it adds my rows as columns. Is it possible to reverse the grid, or maybe there is another way to create the required table?

UPDATE

Here is my code:

@SpringComponent
@UIScope
public class MyDataEditor extends VerticalLayout {
private final MyDataRepository repository;
private MyData myData;

TextField month = new TextField("Period");
TextField numberOfWorkers = new TextField(" Number of workers");
TextField numberOfNewcomers = new TextField("Number of newcomers");
TextField numberOfDismissals = new TextField("Number of dismissals");

Button save = new Button("Save");
Button cancel = new Button("Cancel");
Button delete = new Button("Delete");
CssLayout actions = new CssLayout(save, cancel, delete);

Binder<MyData> binder = new Binder<>(MyData.class);

@Autowired
public MyDataEditor(MyDataRepository repository) {
    this.repository = repository;
    addComponents(month, numberOfWorkers, numberOfNewcomers, numberOfDismissals, actions);
    binder.bindInstanceFields(this); 
    setSpacing(true);
    actions.setStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
    save.setStyleName(ValoTheme.BUTTON_PRIMARY);
    save.setClickShortcut(ShortcutAction.KeyCode.ENTER);

    save.addClickListener(e -> repository.save(myData));
    delete.addClickListener(e -> repository.delete(myData));
    cancel.addClickListener(e -> editInputData(myData));
    setVisible(false);
}

public interface ChangeHandler {
    void onChange();
}

public final void editMyData(MyData c) {
    if (c == null) {
        setVisible(false);
        return;
    }
    final boolean persisted = c.getMonth() != null;
    if (persisted) {
        myData = repository.findOne(c.getMonth());
    } else {
        myData = c;
    }
    cancel.setVisible(persisted);
    binder.setBean(myData);
    save.focus();
    periodId.selectAll();
}

public void setChangeHandler(ChangeHandler h) {
    save.addClickListener(e -> h.onChange());
    delete.addClickListener(e -> h.onChange());
}

}


@SpringUI
@Theme("valo")
public class VaadinUI extends UI {
private final MyDataRepository repo;
private final MyDataEditor editor;
final Grid<MyData> grid;
private final Button addNewBtn;

@Autowired
public VaadinUI(MyDataRepository repo, MyDataEditor editor) {
    this.repo = repo;
    this.editor = editor;
    this.grid = new Grid<>(MyData.class);
    this.addNewBtn = new Button("Add new month");
}

@Override
protected void init(VaadinRequest request) {

    grid.setHeight(300, Unit.PIXELS);
    grid.setColumns("month", "numberOfWorkers", "numberOfNewcomers", "numberOfDismissals");
    grid.asSingleSelect().addValueChangeListener(e -> {
        editor.editMyData(e.getValue());
    });
    addNewBtn.addClickListener(e -> editor.editMyData(new MyData()));
    editor.setChangeHandler(() -> {
        editor.setVisible(false);
        grid.setItems(repo.findAll());
    });
}
}

      

So what I mean by this question is what I installed

grid.setColumns("month", "numberOfWorkers", "numberOfNewcomers", "numberOfDismissals");

      

and don't recognize the type method setRows

, so my table looks like this: https://www.screencast.com/t/ndDY6tXp but should be like the first picture.

-1


source to share


2 answers


I truly believe that there is no way to solve this gracefully without CSS or extending the client's grid component.

What you could do is add your data using



List<MyData> data = repo.findAll();
for(int i = 0; i < data.size(); i++)
    grid.addColumn(i)

//String[] months = data.map(x -> x.month).collect(Collectors.toArray)
//String[] nrWork = data.map(x -> x.nrWork).collect(Collectors.toArray)
grid.addRow(months)
grid.addRow(nrWork)

      

0


source


I believe the Vaadin grid (or table) component was designed with the concept of a table as a starting point. Therefore, you will have a single column-defined structure that displays any number of data items of the same type, 1 per row. And as far as I know, prior to 8.0.4, you cannot rotate the structure.

Also, from a user perspective, if you have multiple time periods, it will be easier to scroll vertically (using the mouse wheel) than horizontally, so I suggest discussing the possibility of displaying them the same way you started with the "month "," numberOfWorkers "," numberOfNewcomers "and" numberOfDismissals "and supplied the strings MyData

. It also makes it easier to sort, filter, add or edit the selected items, whereas for the workaround below you need to do something extra.

If this is not acceptable for some reason, you should be able to spoof the function you want with a little work (see sample below), but performance and usability are wise, there are no guarantees ... after all, this is not what it is for.

code



package com.example.grid;

import com.vaadin.data.ValueProvider;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Notification;
import com.vaadin.ui.VerticalLayout;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.function.Function;

public class HorizontalGrid extends VerticalLayout {

    private static final String ROW_CAPTION = "row-caption";

    public HorizontalGrid() {
        // basic grid setup without column header
        Grid<HorizontalDisplayAdapter> grid = new Grid<>();
        grid.setSizeFull();
        grid.setSelectionMode(Grid.SelectionMode.NONE);
        grid.removeHeaderRow(0);

        // load some data from the DB or someplace else
        List<PeriodSummary> periods = loadPeriods();

        // add row headers
        grid.addColumn(HorizontalDisplayAdapter::getCaption).setId(ROW_CAPTION).setWidth(150);

        // add a column for each period
        for (int i = 0; i < periods.size(); i++) {
            // save the column index so we ca figure out what to edit later
            grid.addColumn(new AdapterValueProvider(i)).setId(String.valueOf(i)).setWidth(60);
        }

        // wrap the data in "horizontal display adapters"
        grid.setItems(
                new HorizontalDisplayAdapter("Period", periods, PeriodSummary::getPeriod),
                new HorizontalDisplayAdapter("Workers", periods, PeriodSummary::getWorkers),
                new HorizontalDisplayAdapter("Newcomers", periods, PeriodSummary::getNewcomers),
                new HorizontalDisplayAdapter("Dismissals", periods, PeriodSummary::getDismissals)
        );

        // retrieve the correct period summary to edit, based on the column that was clicked (unless it the header)
        grid.addItemClickListener(event -> {
            if (!ROW_CAPTION.equals(event.getColumn().getId())) {
                Integer columnIndex = Integer.valueOf(event.getColumn().getId());
                Notification.show("Editing " + event.getItem().getSummary(columnIndex), Notification.Type.ERROR_MESSAGE);
            }
        });

        // freeze first column for scrolling purposes
        grid.setFrozenColumnCount(1);

        addComponent(grid);
        setSizeFull();
    }

    // generate some dummy data to simulate loading from the DB
    private List<PeriodSummary> loadPeriods() {
        Random random = new Random();
        ArrayList<PeriodSummary> periodSummaries = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            periodSummaries.add(new PeriodSummary(i, random.nextInt(100), random.nextInt(100), random.nextInt(100)));
        }
        return periodSummaries;
    }

    // adapter to display data in a "horizontal format"
    public class HorizontalDisplayAdapter {
        // row caption
        private final String caption;

        // periods for each column
        private final List<PeriodSummary> periods;

        // used for brevity, a class hierarchy is probably more elegant
        private Function<PeriodSummary, Integer> valueExtractor;

        public HorizontalDisplayAdapter(String caption, List<PeriodSummary> periods, Function<PeriodSummary, Integer> valueExtractor) {
            this.caption = caption;
            this.periods = periods;
            this.valueExtractor = valueExtractor;
        }

        public String getCaption() {
            return caption;
        }

        public PeriodSummary getSummary(int columnIndex) {
            return periods.get(columnIndex);
        }

        // extract the data for a certain column
        public Integer getValue(int columnIndex) {
            return valueExtractor.apply(periods.get(columnIndex));
        }
    }

    // basic bean
    public class PeriodSummary {
        int period;
        int workers;
        int newcomers;
        int dismissals;

        public PeriodSummary(int period, int workers, int newcomers, int dismissals) {
            this.period = period;
            this.workers = workers;
            this.newcomers = newcomers;
            this.dismissals = dismissals;
        }

        public int getPeriod() {
            return period;
        }

        public void setPeriod(int period) {
            this.period = period;
        }

        public int getWorkers() {
            return workers;
        }

        public void setWorkers(int workers) {
            this.workers = workers;
        }

        public int getNewcomers() {
            return newcomers;
        }

        public void setNewcomers(int newcomers) {
            this.newcomers = newcomers;
        }

        public int getDismissals() {
            return dismissals;
        }

        public void setDismissals(int dismissals) {
            this.dismissals = dismissals;
        }

        @Override
        public String toString() {
            return "PeriodSummary{" +
                    "period=" + period +
                    ", workers=" + workers +
                    ", newcomers=" + newcomers +
                    ", dismissals=" + dismissals +
                    '}';
        }
    }

    // value provider for the horizontal display adapters
    private class AdapterValueProvider implements ValueProvider<HorizontalDisplayAdapter, Integer> {
        // column index is used to retrieve data from the correct summary
        private int columnIndex;

        public AdapterValueProvider(int columnIndex) {
            this.columnIndex = columnIndex;
        }

        @Override
        public Integer apply(HorizontalDisplayAdapter horizontalDisplayAdapter) {
            return horizontalDisplayAdapter.getValue(columnIndex);
        }
    }
}

      

Result

"Horizontal grid

0


source







All Articles