Vaadin 21 Grid预选中项未在UI显示,如何正确实现Grid条目预选功能?
这个问题不是Vaadin的Bug,也不是你漏了Push之类的配置,核心原因是Person实体类没有正确重写equals和hashCode方法。
Vaadin Grid前端渲染选中状态的逻辑是:拿后端标记为选中的对象,和Grid当前数据源里的所有条目做equals对比,只有匹配到的条目才会在前端显示勾选状态。你场景里两个来源的Person对象不等:
event.getInvolved()里的Person是查询Event时级联加载的实例- Grid的数据源是单独调用
personRepository.findAll()查询出来的实例
两者是同一条数据库记录对应的不同Java堆对象,如果没有重写equals方法,默认用对象内存地址判断相等,Grid就认为你要选中的对象不在当前数据源里,自然不会渲染勾选。而后端的选中集合只是简单把你传入的对象加了进去,所以你点击调试按钮能拿到全部选中项。
有两种解决方案:
方案1:重写Person类的equals和hashCode方法
基于业务主键(一般是id字段)实现相等判断即可,注意不要用到懒加载的关联字段避免触发额外查询或者NPE。
如果用Lombok可以直接加注解:
@Entity @EqualsAndHashCode(onlyExplicitlyIncluded = true) public class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @EqualsAndHashCode.Include private Long id; // 其他字段 }
手动实现的话参考写法:
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return id != null && id.equals(person.id); } @Override public int hashCode() { return getClass().hashCode(); }
方案2:从Grid数据源中获取实例后再选中
如果不想修改实体的equals逻辑,可以在预选时先从Grid的数据源里找到对应ID的实例,再调用select方法:
private void updateView() { persons.deselectAll(); List<Person> gridPersons = persons.getListDataView().getItems().toList(); for (Person related : event.getInvolved()) { gridPersons.stream() .filter(p -> p.getId().equals(related.getId())) .findFirst() .ifPresent(persons::select); } }
两种方案都可以解决你遇到的前端不显示预选条目的问题。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

