Vaadin Data Binder绑定ComboBox时下拉框选中标记异常问题
问题根源
- Vaadin ComboBox默认通过
equals()方法判断选中值和下拉选项是否为同一对象。你在ValueProvider的apply方法中每次都新建了Person实例,哪怕属性和下拉列表options中的实例完全一致,默认equals实现是判断内存地址,两个对象并不相等,因此Binder无法匹配到下拉列表中已有的选项,无法正确渲染选中标记。 - 多个对勾同时存在的原因也是同理:每次绑定值更新时返回的都是全新的
Person实例,旧的选中实例没有被匹配为「未选中」,新的实例又被标记为选中,就会出现多个对勾共存的异常。 - 你补充的显示值为
String、实际值为Integer的ComboBox异常,本质也是值匹配逻辑不一致导致的。
解决方案
方案1:重写Person类的equals和hashCode方法
以业务唯一标识id作为相等判断依据,不需要修改绑定逻辑即可解决匹配问题:
import java.util.Objects; // 以下代码添加到Person类中 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return Objects.equals(id, person.id); } @Override public int hashCode() { return Objects.hash(id); }
方案2:修改ValueProvider逻辑,直接从下拉选项中查找实例
不要新建Person对象,从已经设置给ComboBox的options列表中查找id匹配的实例返回,同时建议在Setter中同步存储id,避免后续匹配异常:
binder.bind(combobox, new ValueProvider<Map, Person>() { @Override public Person apply(final Map p) { Long targetId = (Long) p.get("id"); // 从已加载的选项列表中查找匹配实例 return options.stream() .filter(person -> person.getId().equals(targetId)) .findFirst() .orElse(null); } }, new Setter<Map, Person>() { @Override public void accept(final Map bean, final Person p) { // 同步存储id和name,保证后续匹配逻辑正常 bean.put("id", p.getId()); bean.put("name", p.getName()); } });
针对显示值、实际值类型不同的ComboBox的补充说明
如果ComboBox值类型为Integer、仅显示文本为String,可以直接将ComboBox声明为ComboBox<Integer>,通过setItemLabelGenerator将Integer转换为对应显示文本,避免自定义类型的匹配问题。
内容的提问来源于stack exchange,提问作者Antonio
相关产品推荐
相关产品推荐

