我正在开发一个Vaadin
应用,我决定使用SuggestingComboBox
这个想法,可以更好地搜索项目。这很好用,但现在我无法弄清楚如何使用setNewItemHandler
方法添加尚未包含在容器中的新元素。
对于参考,这里是SuggestingComBox
代码:
public class SuggestingComboBox extends ComboBox {
public SuggestingComboBox() {
setItemCaptionMode(ItemCaptionMode.PROPERTY);
setItemCaptionPropertyId("name");
}
@Override
protected Filter buildFilter(String filterString,
FilteringMode filteringMode) {
return new SuggestingContainer.SuggestionFilter(filterString);
}
}
组合框中出现的SuggestingContainer
代码:
public abstract class SuggestingContainer<T> extends BeanItemContainer<T> {
public SuggestingContainer(Class<? super T> type)
throws IllegalArgumentException {
super(type);
}
@Override
protected void addFilter(Filter filter)
throws UnsupportedFilterException {
if(filter instanceof SuggestionFilter) {
SuggestionFilter suggestionFilter = (SuggestionFilter) filter;
filterItems(suggestionFilter.getFilterString());
} else
super.addFilter(filter);
}
//This method is to be overriden
protected abstract void filterItems(String filterString);
public static class SuggestionFilter implements Container.Filter {
private String filterString;
public SuggestionFilter(String filterString) {
this.filterString = filterString;
}
public String getFilterString() {
return filterString;
}
@Override
public boolean passesFilter(Object itemId, Item item)
throws UnsupportedOperationException {
return false;
}
@Override
public boolean appliesToProperty(Object propertyId) {
return false;
}
}
此容器用作:
public SuggestingField extends CustomField<Model> {
private SuggestingComboBox suggestingCB;
private SuggestingContainer<ObjectItem> container;
public SuggestingField() {
suggestingCB = new SuggestingComboBox();
container = new SuggestingContainer<ObjectItem>(ObjectItem.class) {
@Override
protected void filterItems(String filterString) {
removeAllItems();
List<Model> result; //Obtain here the results
List<ObjectItem> lItems = result.stream()
.map(m -> new ObjectItem(m.getId()+"", m.toString(), m))
.collect(Collectors.toList());
addAll(lItems);
}
};
suggestingCB.setContainerDataSource(container);
suggestingCB.setImmediate(true);
suggestingCB.setItemCaptionPropertyId("text");
}
}
另外,我有一个POJO Model
和ObjectItem
类,我必须使用,因为我无法使用toString
字幕模式。
public class Model {
private int id;
private String name;
//Getters and setters; equals/hash
}
public class ObjectItem {
private String id;
private String text;
private Object o;
//Equals/hash and getters/setters
}
所以,我的问题是:我正在尝试允许使用Model
方法在字段中创建新的setNewItemHandler
(s)。这是我到目前为止所尝试过的。
public SuggestingField extends CustomField<Model> {
...
public void setNewElementsAllowed(boolean allowed) {
this.suggestingCB.setNewItemsAllowed(allowed);
this.suggestingCB.setImmediate(allowed);
if(allowed) {
suggestingCB.setNewItemHandler(caption -> {
Model m = new Model();
m.setNombre(caption);
setValue(m);
});
}
}
public void setValue(Model m) {
super.setValue(m);
if(m == null)
suggestingCB.setValue(null);
else {
ObjectItem it = new ObjectItem(""+m.getId(),
m.getName(), m);
if(container.size() == 0 || !container.containsId(it.getId()))
container.addItem(it);
suggestingCB.setValue(it);
suggestingCB.select(it);
}
}
调试完这段代码之后,我发现使用了newElementHandler
,并且它向容器中添加了一个新项,但ComboBox
和下一个处理程序的执行中没有显示任何内容,容器为空,好像没有插入任何项目。
答案 0 :(得分:0)
我已经能够识别错误。当您在ComboBox
中选择一个项目时,filterString
会变为""
,因此,如果您选择了数据库中没有的内容,并回想起查询,则会赢得&# 39; t在List<Model> result
中,因此,它将被取消选择
解决此问题的一种方法是修改SuggestingField
,如下所示:
public SuggestingField extends CustomField<Model> {
private Model model;
...
public SuggestingField() {
...
container = new SuggestingContainer<ObjectItem>(ObjectItem.class) {
@Override
protected void filterItems(String filterString) {
removeAllItems();
if("".equals(filterString)) {
if(model != null) {
ObjectItem it = new ObjectItem();
it.setId(model.getId()+"");
it.setText(model.toString());
it.setObject(model);
addItem(it);
return;
}
}
List<Model> result; //Obtain here the results
List<ObjectItem> lItems = result.stream()
.map(m -> new ObjectItem(m.getId()+"", m.toString(), m))
.collect(Collectors.toList());
addAll(lItems);
}
};
suggestingCB.addValueChangeListener(ev -> {
this.model = (Model) suggestingCB.getValue();
});
这允许通过过滤器维护新项目。