You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vaadin 8 Grid组件编辑模式下动态计算列值

Vaadin 8 Grid 实时计算列C(A+B)实现方案

无需JavaScript的实现方案

Vaadin 8 Grid可以通过绑定数据模型的属性变更实现实时计算,完全不需要依赖JavaScript,这也是最符合Vaadin组件设计思想的方案:

1. 定义带自动计算逻辑的数据实体

给A、B字段的setter方法添加计算逻辑,当A或B的值修改时,自动更新C的值:

public class DataItem {
    private Double a;
    private Double b;
    private Double c;

    public Double getA() { return a; }
    public void setA(Double a) {
        this.a = a;
        calculateC();
    }

    public Double getB() { return b; }
    public void setB(Double b) {
        this.b = b;
        calculateC();
    }

    // C为只读计算值,不需要setter
    public Double getC() { return c; }

    private void calculateC() {
        this.c = (a != null ? a : 0) + (b != null ? b : 0);
    }
}

2. 配置Grid编辑器

将Grid的编辑器组件与实体属性绑定,当用户修改A/B的值时,Binder会自动调用实体的setter方法,触发C的计算并实时刷新显示:

Grid<DataItem> grid = new Grid<>(DataItem.class);
grid.setColumns("a", "b", "c");

// 启用编辑器
grid.getEditor().setEnabled(true);
Binder<DataItem> binder = grid.getEditor().getBinder();

// 配置A列编辑器
TextField aField = new TextField();
binder.forField(aField)
      .withConverter(StringToDoubleConverter.forNumberField("请输入有效数字"))
      .bind(DataItem::getA, DataItem::setA);
grid.getColumn("a").setEditorComponent(aField);

// 配置B列编辑器
TextField bField = new TextField();
binder.forField(bField)
      .withConverter(StringToDoubleConverter.forNumberField("请输入有效数字"))
      .bind(DataItem::getB, DataItem::setB);
grid.getColumn("b").setEditorComponent(bField);

// 标记C列为不可编辑
grid.getColumn("c").setEditable(false);

用户在编辑模式下修改A/B的值后,C列会自动显示计算结果,无需点击保存按钮。

必须使用JavaScript的场景解决方法

如果因业务限制无法修改数据实体,可通过Vaadin的客户端API绑定事件,解决Grid DOM元素无ID的问题:

核心思路

利用Vaadin组件的ElementAPI给编辑器组件绑定blur事件,通过DOM层级关系定位当前行的元素,完成计算后更新C列内容:

Grid<DataItem> grid = new Grid<>(DataItem.class);
grid.setColumns("a", "b", "c");
grid.getEditor().setEnabled(true);
Binder<DataItem> binder = grid.getEditor().getBinder();

// 配置A列编辑器并绑定blur事件
TextField aField = new TextField();
binder.bind(aField, DataItem::getA, DataItem::setA);
grid.getColumn("a").setEditorComponent(aField);

aField.getElement().addEventListener("blur", event -> {
    // 编写JS片段,通过DOM层级定位元素
    String jsCode = "var currentRow = $0.closest('.v-grid-row'); " +
                    "var aValue = parseFloat($0.value) || 0; " +
                    "var bInput = currentRow.querySelector('.v-text-field:nth-child(2) input'); " +
                    "var bValue = parseFloat(bInput.value) || 0; " +
                    "var cCell = currentRow.querySelector('.v-grid-cell:nth-child(3)'); " +
                    "cCell.textContent = (aValue + bValue).toFixed(2);";
    aField.getElement().executeJavaScript(jsCode);
});

// 配置B列编辑器并绑定blur事件
TextField bField = new TextField();
binder.bind(bField, DataItem::getB, DataItem::setB);
grid.getColumn("b").setEditorComponent(bField);

bField.getElement().addEventListener("blur", event -> {
    String jsCode = "var currentRow = $0.closest('.v-grid-row'); " +
                    "var bValue = parseFloat($0.value) || 0; " +
                    "var aInput = currentRow.querySelector('.v-text-field:nth-child(1) input'); " +
                    "var aValue = parseFloat(aInput.value) || 0; " +
                    "var cCell = currentRow.querySelector('.v-grid-cell:nth-child(3)'); " +
                    "cCell.textContent = (aValue + bValue).toFixed(2);";
    bField.getElement().executeJavaScript(jsCode);
});

// 标记C列为不可编辑
grid.getColumn("c").setEditable(false);

代码说明

  • $0是Vaadin内置的变量,指代当前触发事件的DOM元素
  • 通过closest('.v-grid-row')定位当前编辑行
  • 用querySelector根据列的顺序(nth-child索引)找到同行情报的输入框和C列单元格
  • 计算后直接修改C列单元格的文本内容

内容的提问来源于stack exchange,提问作者Hessam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 18:50:26