Vaadin 8:如何实现带折叠/展开表头的简单Grid(兼容IE)
嘿,作为Vaadin 8的新手,你这个需求真的不用大动干戈用TreeGrid,我给你两个简单又兼容IE8+的方案,完全贴合你的需求:
方案一:自定义表头组件+Grid行可见性控制
这个方案的思路是自己做一个带箭头的表头栏,然后控制Grid本身的行显示/隐藏,初始状态下只显示我们自定义的表头,点击箭头后展开所有行。
步骤&代码示例
- 首先定义你的数据实体类:
public class MyData { private String col1; private String col2; public MyData(String col1, String col2) { this.col1 = col1; this.col2 = col2; } // 必须提供Getter方法,Vaadin Grid需要通过它获取数据 public String getCol1() { return col1; } public String getCol2() { return col2; } }
- 在UI中实现自定义表头和Grid的逻辑:
public class MyUI extends UI { @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout mainLayout = new VerticalLayout(); mainLayout.setMargin(true); mainLayout.setSpacing(true); setContent(mainLayout); // 模拟你的数据列表 List<MyData> dataList = Arrays.asList( new MyData("第一行第一列", "第一行第二列"), new MyData("第二行第一列", "第二行第二列"), new MyData("第三行第一列", "第三行第二列") ); // 创建Grid并配置列 Grid<MyData> dataGrid = new Grid<>(MyData.class); dataGrid.setItems(dataList); dataGrid.removeAllColumns(); // 移除自动生成的列,方便对齐自定义表头 dataGrid.addColumn(MyData::getCol1).setWidth("50%"); dataGrid.addColumn(MyData::getCol2).setWidth("50%"); // 自定义表头行:带箭头的点击区域 HorizontalLayout customHeader = new HorizontalLayout(); customHeader.setWidth("100%"); customHeader.setStyleName("grid-custom-header"); customHeader.setDefaultComponentAlignment(Alignment.MIDDLE_LEFT); customHeader.setSpacing(true); // 箭头标签,用FontAwesome图标(Vaadin 8内置支持) Label toggleArrow = new Label(FontAwesome.CHEVRON_RIGHT.getHtml()); toggleArrow.setContentMode(ContentMode.HTML); toggleArrow.addStyleName("header-toggle-arrow"); // 给箭头加点击事件,也可以给整个表头加,看你需求 toggleArrow.addClickListener(e -> toggleGridRows(dataGrid, toggleArrow)); // 列标题 Label col1Title = new Label("列1"); Label col2Title = new Label("列2"); col2Title.setWidth("50%"); col2Title.setStyleName("header-column-title"); customHeader.addComponents(toggleArrow, col1Title, col2Title); customHeader.setExpandRatio(col2Title, 1); // 让第二列标题占满剩余宽度 // 把自定义表头和Grid加入主布局 mainLayout.addComponents(customHeader, dataGrid); // 初始状态隐藏Grid的所有行,只显示自定义表头 dataGrid.setRowsVisible(false); // 隐藏Grid默认的表头,避免重复 dataGrid.addStyleName("hide-default-header"); } // 封装切换行显示/隐藏的逻辑 private void toggleGridRows(Grid<?> grid, Label arrowLabel) { boolean isRowsVisible = grid.isRowsVisible(); grid.setRowsVisible(!isRowsVisible); // 切换箭头图标 arrowLabel.setValue(isRowsVisible ? FontAwesome.CHEVRON_RIGHT.getHtml() : FontAwesome.CHEVRON_DOWN.getHtml()); } @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true) @VaadinServletConfiguration(ui = MyUI.class, productionMode = false) public static class MyUIServlet extends VaadinServlet { } }
- 加一点CSS样式,让表头看起来更协调(可以放在你的theme.scss里):
.grid-custom-header { background-color: #f0f0f0; border: 1px solid #e0e0e0; padding: 8px 12px; cursor: pointer; /* 提示用户可以点击 */ } .header-toggle-arrow { font-size: 14px; color: #333; } .header-column-title { font-weight: bold; } .hide-default-header .v-grid-header { display: none; }
方案二:复用Grid默认表头实现切换
如果你不想自己做表头,可以直接给Grid默认的表头单元格加箭头和点击事件,控制行的显示,代码更简洁:
代码示例
public class MyUI extends UI { @Override protected void init(VaadinRequest vaadinRequest) { VerticalLayout mainLayout = new VerticalLayout(); mainLayout.setMargin(true); setContent(mainLayout); List<MyData> dataList = Arrays.asList( new MyData("数据1-1", "数据1-2"), new MyData("数据2-1", "数据2-2") ); Grid<MyData> dataGrid = new Grid<>(MyData.class); dataGrid.setItems(dataList); dataGrid.setColumnOrder("col1", "col2"); // 获取Grid默认的表头行 Grid.HeaderRow headerRow = dataGrid.getDefaultHeaderRow(); Grid.HeaderCell firstColHeader = headerRow.getCell(dataGrid.getColumn("col1")); // 给第一列表头设置带箭头的内容 Label headerContent = new Label(FontAwesome.CHEVRON_RIGHT.getHtml() + " 列1"); headerContent.setContentMode(ContentMode.HTML); headerContent.setStyleName("clickable-header"); firstColHeader.setComponent(headerContent); // 初始隐藏行 dataGrid.setRowsVisible(false); // 表头点击事件 headerContent.addClickListener(e -> { boolean visible = dataGrid.isRowsVisible(); dataGrid.setRowsVisible(!visible); // 更新箭头和标题 String arrowHtml = visible ? FontAwesome.CHEVRON_RIGHT.getHtml() : FontAwesome.CHEVRON_DOWN.getHtml(); headerContent.setValue(arrowHtml + " 列1"); }); mainLayout.addComponent(dataGrid); } // 数据类和Servlet部分和方案一一致,这里省略 }
对应的CSS:
.clickable-header { cursor: pointer; font-weight: bold; }
兼容性说明
这两个方案都只用了Vaadin 8的核心组件(Grid、HorizontalLayout、Label等),完全兼容IE8及以上版本。如果你的项目还没配置IE8兼容,记得在web.xml里加下面的配置:
<context-param> <param-name>vaadin.ie8.compatibility</param-name> <param-value>true</param-value> </context-param>
作为Vaadin新手,这种组合核心组件的方式既轻量又容易维护,完全没必要用TreeGrid这种复杂组件~
内容的提问来源于stack exchange,提问作者T. Phillips
相关产品推荐
相关产品推荐

