Vaadin - 在行修改后刷新网格

10

我使用数据库中的数据创建了一个简单的网格:

BeanItemContainer<Customer> container = new BeanItemContainer<>(Customer.class, customerRepository.findAll());
Grid grid = new Grid(container);

为了编辑每一行,创建了这个按钮:

Button edit = new Button("Edit", clickEvent -> openWindow((Customer) grid.getSelectedRows().iterator().next()));

打开这个编辑表单窗口后,所有的更改都被接受之后,我必须手动刷新整个页面才能在网格上看到修改。我的问题是:

如何在任何行的条目修改后只刷新网格? 如何将这些修改保存到数据库中(也许beanItemContainer可以做到)?


请参考类似问题(https://stackoverflow.com/q/51871370/642706),但是针对的是Vaadin 8而不是7。 - Basil Bourque
5个回答

12

Vaadin 8提供以下方法,在行添加或删除,或基础数据发生更改后刷新网格:

grid.getDataProvider().refreshAll();

3
很遗憾,这在 Vaadin 8 中不起作用。我需要每次显式地设置项目。 - Aubergine
2
@Aubergine 如果你一开始使用 setItems() 设置数据,那么是的,因为它会创建一个包装项目列表的 DataProvider,所以你需要显式地更新项目。 - sofend
1
@Aubergine 如果您使用一个动态从数据存储(例如关系型数据库)获取数据的 DataProvider,那么 refreshAll() 方法将按照其所述的方式正常工作。 - sofend

10

这是一个bug。在基础容器中进行更改后,网格不会自动更新,也没有任何合理的方法来刷新。有几种解决此问题的hack方法,例如:

grid.clearSortOrder();
或者
grid.setEditorEnabled(true);
grid.setEditorEnabled(false);

SSCCE:

TextField text =  new TextField("Edit");
Grid grid;
BeanItemContainer<Customer> container;

@Override
protected void init(VaadinRequest request) {
    final VerticalLayout layout = new VerticalLayout();
    container = new BeanItemContainer<>(Customer.class, Arrays.asList(new Customer("1"), new Customer("2")));
    grid = new Grid(container);
    Button open = new Button("open");
    open.addClickListener(this :: openListener);
    Button save = new Button("save");
    save.addClickListener(this :: saveListener);
    layout.addComponents(grid, open, save, text);
    setContent(layout);
}

private void openListener(Button.ClickEvent clickEvent){
    text.setValue(((Customer) (grid.getSelectedRow())).getName());
}
private void saveListener(Button.ClickEvent clickEvent){
    Customer c = (Customer) grid.getSelectedRow();
    c.setName(text.getValue());
    grid.clearSortOrder();
}

可能是重复的问题 在Vaadin 7.4应用程序中使用新数据更新网格


非常感谢。您提供的 clearSortOrder() 建议完美地解决了问题。 此外,对于任何想要刷新单个行的人,这里有一些提示: Vaadin 论坛 - jsosnowski
如果这是一个 bug,你有相关的 Vaadin bug 追踪器编号/链接吗? - Dominic

1

这是一个方法,但它什么也不做(Vaadin 7.7.9) - FiruzzZ
我在发布这个答案时(大约一年前)它曾经工作过。如果我是你,我会检查容器中的数据是否是最新的。 - user1411778
当网格被禁用时,添加或修改行时**refreshAllRows()无效,但clearSortOrder()**有效。 - FiruzzZ
这些家伙甚至控制不了他们的API。刷新表格真是麻烦。你只需要给它一个项目列表,它就应该呈现出来,有多难呢?被迫在工作中使用Vaadin,我讨厌它。我已经从事Web开发15年了,从未遇到过这种烂摊子。 - html_programmer

0

我不得不在每次调用saveListener事件后显式调用grid.setItems(),以使我的Vaadin 8.3 Grid刷新网格内的数据。奇怪的是,视觉网格状态不会反映编辑后的值。

Scala实现:

var advicesList : mutable.MutableList[Advice] = null

private def initGrid() = {
  advicesList = mutable.MutableList(itmemsFromDB: _*)
  setItems(advicesList.asJava)

  getEditor.addSaveListener((event) => {
      val bean = event.getBean
      Notification.show("Saved value: " + bean)

      // ==== RELOAD GRID ITEMS AFTER EDITION
      val oldItemIdx = advicesList.indexOf(advicesList.filter(a => a.id == bean.id).head)
      advicesList.update(oldItemIdx, bean)
      event.getGrid.setItems(advicesList.asJava)
  })
}

0

有一种更好的解决问题的方法:

您需要从容器中获取BeanItem并将其传递到编辑器窗口。在那里,您可以通过访问BeanItemProperties来更改bean本身。这是非常手动的工作,所以我总是使用FieldGroup的数据绑定 - 只需调用bind(field,"propertyName");其中propertyName是getter方法,不包括get和非大写字母。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接