[英]How do I pre-select items in a Vaadin 21 Grid? Selection is not displayed in the UI
我已经定义了一个实现BeforeEnterObserver
的布局。 在beforeEnter
方法中,我从数据库加载了一个 object 实例。 该实例与其他对象有关系。 同样在这个方法中,我调用了另一个 Layout 的方法,它设置 bean 并尝试在 Grid 中预选项目:
public void setBean(BeanClass bean) {
binder.setBean(bean);
relationGrid.deselectAll();
for(Person person : bean.getRelated()) {
relationGrid.getGrid().select(person);
}
Set<Person> selected = involvedGrid.getGrid().getSelectedItems();
}
最后一行用于调试。 我可以看到,已加载的 bean 正在正确选择相关实例。
网格在布局内的自己的 class 中定义,并且具有多选且没有全选复选框和搜索字段:
grid.setSelectionMode(Grid.SelectionMode.MULTI);
GridMultiSelectionModel<Person> selectionModel = (GridMultiSelectionModel<Person>) grid.getSelectionModel();
selectionModel.setSelectAllCheckboxVisibility(GridMultiSelectionModel.SelectAllCheckboxVisibility.HIDDEN);
Grid 布局被注入到表单视图中,表单视图被注入到编辑视图中。
现在在 Browser 中显示编辑视图时,Grid 中的相关 object 没有被选中。 我在编辑视图中配置了一个按钮,以显示所选项目,用于调试目的:
cancel.addClickListener(e -> {
Set<Person> selectedPersons = form.getRelatedGrid().getSelectedItems();
for(Person person : selectedPersons)
Notification.show(person.getDisplayName());
});
如果我单击该按钮,它会正确显示相关人员的姓名。 如果我然后 select 另一个人并再次单击,它正确地将两个选定的人显示为通知,但在网格中只选择了第二个。
表单的字段已正确填写,如上所示,我之后直接处理关系。
我也尝试启用推送模式
@Push
public class Application extends SpringBootServletInitializer implements AppShellConfigurator {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
这不会改变网格的行为。
为了简单起见,在和大图讨论之后,我做了一个测试视图。 同样的问题仍然存在。
@Route(value = "event/:id([0-9]+)/edit_test", layout = MainLayout.class)
public class EditEventTest extends VerticalLayout implements BeforeEnterObserver, AfterNavigationObserver {
private final EventRepository eventRepository;
private final PersonRepository personRepository;
private Long id;
private Event event;
private final TextField title = new TextField("Title");
private final Grid<Person> persons = new Grid<>(Person.class, false);
private final Button save = new Button("Save");
private final Button test = new Button("Test");
private Binder<Event> binder = new Binder<>(Event.class);
@Autowired
public EditEventTest(EventRepository eventRepository, PersonRepository personRepository) {
this.eventRepository = eventRepository;
this.personRepository = personRepository;
}
@Override
public void beforeEnter(BeforeEnterEvent beforeEnterEvent) {
id = Long.valueOf(beforeEnterEvent.getRouteParameters().get("id").orElseThrow(NotFoundException::new));
Optional<Event> result = eventRepository.findById(id);
this.event = result.orElseThrow(() -> new NoSuchRecordException("Could not find Event with id " + id));
}
@Override
public void afterNavigation(AfterNavigationEvent event) {
buildView();
updateView();
}
private void buildView() {
persons.setSelectionMode(Grid.SelectionMode.MULTI);
GridMultiSelectionModel<Person> selectionModel = (GridMultiSelectionModel<Person>) persons.getSelectionModel();
selectionModel.setSelectAllCheckboxVisibility(GridMultiSelectionModel.SelectAllCheckboxVisibility.HIDDEN);
persons.addColumn(Person::getDisplayName).setHeader("Name");
GridListDataView<Person> dataView = persons.setItems(personRepository.findAll());
FormLayout form = new FormLayout();
add(form);
form.add(title);
form.add(persons);
binder.setBean(event);
binder.bindInstanceFields(this);
HorizontalLayout buttonLayout = new HorizontalLayout();
buttonLayout.addClassName("button-layout");
save.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
buttonLayout.add(save);
buttonLayout.add(test);
add(buttonLayout);
test.addClickListener(e-> {
for (Person p : persons.getSelectedItems())
Notification.show(p.getDisplayName());
});
}
private void updateView() {
persons.deselectAll();
for (Person person : event.getInvolved())
persons.select(person);
}
}
我还尝试将buildView()
移动到构造函数并将binder.setBean(event)
移动到updateView()
。 问题仍然存在。
我在这里缺少什么或者这是一个错误?
您的代码对我来说看起来不错。 我只是建议将数据的获取从 beforeEnter 移到 afterNavigation,但它不应该影响结果。 这是您在更广泛的 scope 中应该考虑的事情,即在肯定需要之前不要从后端加载数据。 例如,您将来可能在其他视图中或在此视图中在 beforeEnter 中进行访问控制。 Hover 这与您的实际问题无关。
这个方法大概可以简化
private void updateView() {
persons.deselectAll();
for (Person person : event.getInvolved())
persons.select(person);
}
至
private void updateView() {
persons.asMultiSelect().setValue(event.getInvolved());
}
但同样,我不希望它改变行为。 如果确实如此,则Grid#select
中存在错误,因为在多选模式下,它不应重置先前的选择。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.