Vaadin 8 - ComboBox 值在 bean 更改后仍然存在
Vaadin 8 - ComboBox value remains after the bean has changed
编辑: 我自己找到了解决方案,如果您只是想提供帮助并且自己没有遇到类似问题,则无需阅读所有内容 ;)
首先,我问过this question in the Vaadin Forum,但我也想在这里问一下,以防万一这不是错误,我只是做错了什么。
我的一个 ComboBox (ComboBox<Bar>
) 依赖于另一个 ComboBox (ComboBox<Foo>
) 的值,当 ComboBox<Foo>
值改变时,它没有按预期更新它的值。
起初,两个组合框都是空的。
当我 select ComboBox<Foo>
的选项时,正在手动重建另一个 ComboBox 的选项。
如果我然后 select ComboBox<Bar>
的选项得到 selected,到现在为止一切都很好。
但是当我现在 select ComboBox<Foo>
的另一个选项时,比方说 none/null,正在重建 ComboBox<Bar>
的选项, 但它的值仍然存在!(应该为空)
这是 eplain/reproduce 我的问题的(简化)代码。我知道这有点多,但我真的想弄清楚我的问题是什么以及我做了什么:
public class FooBar {
private Foo foo = null;
public FooBar(){
}
// getters and setters
...
}
public class Foo {
private Collection<Bar> bars;
private Bar selectedBar = null;
public Foo(Collection<Bar> bars){
this.bars = bars;
}
// getters and setters
...
}
public class Bar {
private String name;
public Bar(String name){
this.name = name;
}
// getters and setters
...
}
在我的视图中,我有一个活页夹和一个组合框,还有一个组合框。它们的设置如下:
Binder<FooBar> binder = new Binder<>(new FooBar());
binder.addValueChangeListener(event -> {
binder.setBean(binder.getBean()); // forces bound components to get the value again / refresh
refillBarOptions();
})
ComboBox<Foo> cbFoo = new ComboBox<>();
cbFoo.setCaption("foo");
Collection<Foo> allFoos = fooService.findAll(); // the foos do NOT have a selectedBar yet
ListDataProvider<Foo> ldpFoo = new ListDataProvider<Foo>(allFoos);
cbFoo.setDataProvider(ldpFoo);
binder.forField(cbFoo)
.bind(
fooBar -> fooBar.getFoo(), //valueprovider
(fooBar, foo) -> fooBar.setFoo(foo) //setter
);
// so initially this combobox' value is empty because the FooBar.getFoo() returns null. thats OK!
ComboBox<Bar> cbBar = new ComboBox<>();
cbBar.setCaption("bar");
cbBar.setDataProvider(new ListDataProvider<Bar>(new HashSet<>())); // no items initially because the Foo-ComboBox has no value yet
cbBar.setItemCaptionGenerator(Bar::getName);
binder.forField(cbBar)
.bind(
fooBar -> fooBar.getFoo() == null ? null : fooBar.getFoo().getSelectedBar(), //valueprovider
(fooBar, bar) -> {
if(fooBar.getFoo() != null){
fooBar.getFoo().setSelectedBar(bar);
}
}
);
cbBar.setEnabled(false) // disable because no items initially
/**
* gets called when binder value has changed.
* This way I circumvent the fact that a normal valueChangeListener of a component is fired before the binder-bean is updated
*/
private void refillBarOptions(){
Foo selectedFoo = binder.getBean().getFoo();
if(selectedFoo != null){
cbBar.setDataProvider<>(new ListDataProvider<>(selectedFoo.getBars())); //cbBar is actually not a local variable so it can be accessed here
cbBar.setEnabled(true);
} else {
// there is no foo selected, therefore no bars should be allowed to be selected
cbBar.setDataProvider(new ListDataProvider<Bar>(new HashSet<>()));
cbBar.setEnabled(false);
}
}
我应该为此开一个新的 Issue 还是我做错了什么?
任何帮助,将不胜感激。谢谢
这里只见树木不见森林..在refillBarOptions()
结束时再次调用binder.setBean(binder.getBean());
解决了问题
private void refillBarOptions(){
Foo selectedFoo = binder.getBean().getFoo();
if(selectedFoo != null){
cbBar.setDataProvider<>(new ListDataProvider<>(selectedFoo.getBars())); //cbBar is actually not a local variable so it can be accessed here
cbBar.setEnabled(true);
} else {
// there is no foo selected, therefore no bars should be allowed to be selected
cbBar.setDataProvider(new ListDataProvider<Bar>(new HashSet<>()));
cbBar.setEnabled(false);
}
binder.setBean(binder.getBean());
}
编辑: 我自己找到了解决方案,如果您只是想提供帮助并且自己没有遇到类似问题,则无需阅读所有内容 ;)
首先,我问过this question in the Vaadin Forum,但我也想在这里问一下,以防万一这不是错误,我只是做错了什么。
我的一个 ComboBox (ComboBox<Bar>
) 依赖于另一个 ComboBox (ComboBox<Foo>
) 的值,当 ComboBox<Foo>
值改变时,它没有按预期更新它的值。
起初,两个组合框都是空的。
当我 select ComboBox<Foo>
的选项时,正在手动重建另一个 ComboBox 的选项。
如果我然后 select ComboBox<Bar>
的选项得到 selected,到现在为止一切都很好。
但是当我现在 select ComboBox<Foo>
的另一个选项时,比方说 none/null,正在重建 ComboBox<Bar>
的选项, 但它的值仍然存在!(应该为空)
这是 eplain/reproduce 我的问题的(简化)代码。我知道这有点多,但我真的想弄清楚我的问题是什么以及我做了什么:
public class FooBar {
private Foo foo = null;
public FooBar(){
}
// getters and setters
...
}
public class Foo {
private Collection<Bar> bars;
private Bar selectedBar = null;
public Foo(Collection<Bar> bars){
this.bars = bars;
}
// getters and setters
...
}
public class Bar {
private String name;
public Bar(String name){
this.name = name;
}
// getters and setters
...
}
在我的视图中,我有一个活页夹和一个组合框,还有一个组合框。它们的设置如下:
Binder<FooBar> binder = new Binder<>(new FooBar());
binder.addValueChangeListener(event -> {
binder.setBean(binder.getBean()); // forces bound components to get the value again / refresh
refillBarOptions();
})
ComboBox<Foo> cbFoo = new ComboBox<>();
cbFoo.setCaption("foo");
Collection<Foo> allFoos = fooService.findAll(); // the foos do NOT have a selectedBar yet
ListDataProvider<Foo> ldpFoo = new ListDataProvider<Foo>(allFoos);
cbFoo.setDataProvider(ldpFoo);
binder.forField(cbFoo)
.bind(
fooBar -> fooBar.getFoo(), //valueprovider
(fooBar, foo) -> fooBar.setFoo(foo) //setter
);
// so initially this combobox' value is empty because the FooBar.getFoo() returns null. thats OK!
ComboBox<Bar> cbBar = new ComboBox<>();
cbBar.setCaption("bar");
cbBar.setDataProvider(new ListDataProvider<Bar>(new HashSet<>())); // no items initially because the Foo-ComboBox has no value yet
cbBar.setItemCaptionGenerator(Bar::getName);
binder.forField(cbBar)
.bind(
fooBar -> fooBar.getFoo() == null ? null : fooBar.getFoo().getSelectedBar(), //valueprovider
(fooBar, bar) -> {
if(fooBar.getFoo() != null){
fooBar.getFoo().setSelectedBar(bar);
}
}
);
cbBar.setEnabled(false) // disable because no items initially
/**
* gets called when binder value has changed.
* This way I circumvent the fact that a normal valueChangeListener of a component is fired before the binder-bean is updated
*/
private void refillBarOptions(){
Foo selectedFoo = binder.getBean().getFoo();
if(selectedFoo != null){
cbBar.setDataProvider<>(new ListDataProvider<>(selectedFoo.getBars())); //cbBar is actually not a local variable so it can be accessed here
cbBar.setEnabled(true);
} else {
// there is no foo selected, therefore no bars should be allowed to be selected
cbBar.setDataProvider(new ListDataProvider<Bar>(new HashSet<>()));
cbBar.setEnabled(false);
}
}
我应该为此开一个新的 Issue 还是我做错了什么? 任何帮助,将不胜感激。谢谢
这里只见树木不见森林..在refillBarOptions()
binder.setBean(binder.getBean());
解决了问题
private void refillBarOptions(){
Foo selectedFoo = binder.getBean().getFoo();
if(selectedFoo != null){
cbBar.setDataProvider<>(new ListDataProvider<>(selectedFoo.getBars())); //cbBar is actually not a local variable so it can be accessed here
cbBar.setEnabled(true);
} else {
// there is no foo selected, therefore no bars should be allowed to be selected
cbBar.setDataProvider(new ListDataProvider<Bar>(new HashSet<>()));
cbBar.setEnabled(false);
}
binder.setBean(binder.getBean());
}