Grid borders rendered incorrectly


How can I fix it?
My grid rendered with this code:

public class AdminView extends VerticalLayout {

    private final Grid<User> grid;
    private final UserService userService;
    private final RoleService roleService;

    public AdminView(UserService userService, RoleService roleService) {
        this.userService = userService;
        this.roleService = roleService;
        setSizeFull();
        grid = generateGrid();
        add(grid);
        add(new Button("Resize", event -> {
            grid.recalculateColumnWidths();
        }));
    }

    private Grid<User> generateGrid() {
        Grid<User> userGrid = new Grid<>(User.class, false);
        userGrid.addColumn(User::getUsername).setHeader("Username").setAutoWidth(true).setFlexGrow(0);
        userGrid.addComponentColumn(user -> {
            TextField textField = new TextField();
            textField.setValue(user.getName());
            textField.addKeyDownListener(Key.ENTER, event -> {
                user.setName(textField.getValue());
                userService.updateUser(user);
            });
            return textField;
        }).setHeader("Name").setResizable(true).setAutoWidth(true).setFlexGrow(0);
        userGrid.addComponentColumn(user -> {
            MultiSelectComboBox<Role> comboBox = new MultiSelectComboBox<>();
            comboBox.setItemLabelGenerator(Role::getRole);
            comboBox.setItems(roleService.findAll());
            comboBox.select(user.getRoles());
            comboBox.addValueChangeListener(event -> {
                user.setRoles(event.getValue());
                userService.updateUser(user);
            });
            comboBox.setSelectedItemsOnTop(true);
            comboBox.setAutoExpand(MultiSelectComboBox.AutoExpandMode.HORIZONTAL);
            return comboBox;
        }).setHeader("Roles").setResizable(true).setAutoWidth(true);
        userGrid.addComponentColumn(user -> {
            Button deleteButton = new Button(VaadinIcon.TRASH.create(), event -> {
                userService.deleteUser(user);
                userGrid.setItems(userService.findAll());
            });
            deleteButton.addThemeVariants(ButtonVariant.LUMO_ERROR);
            return deleteButton;
        }).setHeader("Delete").setWidth("5rem").setFlexGrow(0);
        userGrid.setItems(userService.findAll());
        userGrid.setAllRowsVisible(true);
        userGrid.addThemeVariants(GridVariant.LUMO_ROW_STRIPES);
        userGrid.recalculateColumnWidths();


        userGrid.addClassName(LumoUtility.Overflow.AUTO);
        return userGrid;
    }

}

I don’t see an issue, it renders exactly as configured. You have specified that the columns take only as much space as their need therefore there is still space left. Grid is by default 100% wide

What exactly do you want to do?

I wanted grid to take full possible width without shrinking, but wrapping content if content’s width is smaller than grid’s width. Actually I want to make all columns have width just enough to render all content, but using no more empty space

You have to set flex grow 1 for the column that should take the full space. And it should not be auto width. Also, if the component should take the available column space, it also needs to be set to dynamic width.

For instance:

public class TestView extends VerticalLayout {
    public TestView() {
        setSizeFull();
        Grid<Integer> grid = new Grid<>();
        grid.setWidthFull(); // dynamic width
//        grid.setWidth("700px"); // some fixed width also works

        grid.addColumn(i -> i.toString()).setHeader("Index").setFlexGrow(0).setAutoWidth(true);
        grid.addComponentColumn(i -> new TextField()).setHeader("TF").setFlexGrow(0).setAutoWidth(true);
        grid.addComponentColumn(i -> {
            MultiSelectComboBox<String> box = new MultiSelectComboBox<>();
            box.setItems(List.of("Value A", "Value B", "Value C", "Value D", "Value E", "Value F", "Value G"));
            box.setValue(List.of("Value A", "Value B", "Value C", "Value D", "Value E", "Value F", "Value G"));
            box.setAutoExpand(AutoExpandMode.BOTH);
            box.setWidthFull();
            return box;
        }).setHeader("MSCB").setFlexGrow(1);
        grid.addComponentColumn(i -> new Checkbox()).setHeader("CB").setFlexGrow(0).setAutoWidth(true);


        grid.setItems(IntStream.range(0, 10).boxed().toList());
        add(grid);
    }
}

Results in:

  1. wide

  2. narrow

1 Like

I need it to look something like that:


Making grid take just enough space to render all elements inside, not a single pixel more

Ah ok, now I got you.

Yes, that seems to be not possible out of the box. There are two reasons

  1. the grid has set an align-self: stretched (similar to the form layout). This makes it always full width inside a flex layout. Unfortunately, when setting it to start, the grid becomes a single pixel wide. This is because of 2.

  2. The vaadin-scroller is set to position: absolute. Due to that, the width calculation of the grid breaks, when it does not stretch itself or has a fixed width. You can set the scroller to position: relative and height: 100%using shadow dom styling, but I do not know, if that breaks anything inside the displayment.

I will create a github issue for this use case. Can you check, if that works for you and, if there are any issues resulting out of this workaround, post them here please?

So, I need to do it something like that?

.vaadin-scroller {
    position: relative;
    height: 100%;
}

Not sure if that will affect the scroller inside the grid, but since that will be a global styling, the better way will be to create the following file inside your themes folder:

frontend/themes/your-theme/components/vaadin-grid.css

with the content

#scroller {
    position: relative;
    height: 100%;
}

That doesn’t seem to work. I will stick with making it 100% width then

What does it look like?

I wrote the above out of my memory, so might contain a typo or wrong id. What does the dom in the browser dev tools say?

Just tested it locally and it works. Makes me more interested, why it does not for you. Which Vaadin version do you use?