Vaadin 在编辑模式下,在表的组合框中显示来自IndexedContainers的不同值
简言之:在编辑模式下,我的表格的每个字段中的组合框在选择项目时会给我一个转换错误,但在TableFieldFactory(createField())之外,相同的逻辑和容器工作得非常好。我做错了什么 详细解释: 我有一个包含多个属性(列)和项目(行)的容器。当我编辑连接到此容器的表时,我需要一些列字段上的组合框。我正在使用一个TableFieldFactory来实现这一点,它就像一个魔咒一样工作 我希望每个字段中的组合框包含与其各自属性不同的元素。我的解决方案是在容器类中实现一个方法,该方法迭代容器中的所有属性,并为每个属性创建一个新的IndexedContainer,其中包含该属性的唯一值。该方法返回一个带有propertyID/Containers的映射,这样我在createField()中可以从每个属性中选择每个容器,这些属性是我想要的组合框 示例 假设我有三个propertyId,Foo,Bar和Baz,每个“包含”几个项目,其中一些项目是相同的,如下所示: 福Vaadin 在编辑模式下,在表的组合框中显示来自IndexedContainers的不同值,vaadin,vaadin7,Vaadin,Vaadin7,简言之:在编辑模式下,我的表格的每个字段中的组合框在选择项目时会给我一个转换错误,但在TableFieldFactory(createField())之外,相同的逻辑和容器工作得非常好。我做错了什么 详细解释: 我有一个包含多个属性(列)和项目(行)的容器。当我编辑连接到此容器的表时,我需要一些列字段上的组合框。我正在使用一个TableFieldFactory来实现这一点,它就像一个魔咒一样工作 我希望每个字段中的组合框包含与其各自属性不同的元素。我的解决方案是在容器类中实现一个方法,该方法迭代
- 克里斯
- 克里斯
- 梅格
- 梅格
- 梅格
- 斯图伊
- 斯图伊
Key: PropertyId: Foo
Value: Container: contains propertyId [Foo] and the unique values of Foo, ie. [Chris, Meg, Stewie]
Key: PropertyId: Bar
Value: ... and so forth...
当我准备在createField()中设置容器数据源时,容器如下所示(对于属性Foo):
。。。这对我来说似乎很好
现在,该表按预期显示了每个字段中的组合框。但是,当我单击组合框中的某个项目时,会出现以下转换错误:
com.vaadin.data.util.converter.Converter$ConversionException: Unable to convert value of type java.lang.Integer to model type class java.lang.String. No converter is set and the types are not compatible.
at com.vaadin.data.util.converter.ConverterUtil.convertToModel(ConverterUtil.java:181)
at com.vaadin.ui.AbstractField.convertToModel(AbstractField.java:745)
注意:
我尝试在表外创建相同的场景,效果很好。因此,在TableFieldFactory和createFields()方法之外,具有相同逻辑和相同容器的组合框似乎可以正常工作。我不明白为什么他们不应该在Tablefield工厂工作
问题:
- 如何让组合框设置正确的值?
public class SomeContainer extends IndexedContainer {
private static final long serialVersionUID = 1L;
public void addContainerProperties() {
addContainerProperty("Foo", String.class, null);
addContainerProperty("Bar", String.class, null);
addContainerProperty("Baz", String.class, null);
}
public Map<String, Container> getDistinctContainers() {
Map<String, Container> m = new HashMap<String, Container>();
ArrayList<Object> filter = new ArrayList<Object>();
int id = 0;
for (Object propertyId : this.getContainerPropertyIds()) {
Container cont = new IndexedContainer();
cont.addContainerProperty(propertyId, propertyId.getClass(), null);
for (Object itemId : this.getItemIds()) {
Object ob = ((Item) this.getItem(itemId)).getItemProperty(propertyId).getValue();
if ((!filter.contains(ob.toString())) && (ob != null)) {
filter.add(ob.toString());
Item item = cont.addItem(id);
item.getItemProperty(propertyId).setValue(ob);
id++;
}
}
m.put(propertyId.toString(), cont);
}
return m;
}
}
公共类SomeContainer扩展IndexedContainer{
私有静态最终长serialVersionUID=1L;
public void addContainerProperties(){
addContainerProperty(“Foo”,String.class,null);
addContainerProperty(“Bar”,String.class,null);
addContainerProperty(“Baz”,String.class,null);
}
公共地图getDistinctContainers(){
Map m=新的HashMap();
ArrayList过滤器=新的ArrayList();
int id=0;
对于(对象propertyId:this.GetContainerPropertyId()){
Container=newindexedcontainer();
cont.addContainerProperty(propertyId,propertyId.getClass(),null);
对于(对象itemId:this.getItemIds()){
对象ob=((项)this.getItem(itemId)).getItemProperty(propertyId).getValue();
if((!filter.contains(ob.toString())&&(ob!=null)){
filter.add(ob.toString());
项目=续加项目(id);
item.getItemProperty(propertyId).setValue(ob);
id++;
}
}
m、 put(propertyId.toString(),cont);
}
返回m;
}
}
。。。以下是createField的相关代码:
@Override
public Field<?> createField(Container container, Object itemId, Object propertyId, com.vaadin.ui.Component uiContext) {
TextField tField = (TextField) DefaultFieldFactory.get().createField(container, itemId, propertyId, uiContext);
tField.setImmediate(true);
// ...some code here that uses the TextField
if (propertyId.equals("Foo")) {
ComboBox select = new ComboBox();
for (Map.Entry<String, Container> entry : distinctContainers.entrySet()) {
if (entry.getKey().equals(propertyId)) {
select.setContainerDataSource(entry.getValue());
}
}
select.setImmediate(true);
select.setItemCaptionPropertyId(propertyId);
select.setItemCaptionMode(AbstractSelect.ITEM_CAPTION_MODE_PROPERTY);
return select;
}
// ... if statements for Bar and Baz left out for brevity...
return tField;
}
@覆盖
公共字段createField(容器容器、对象项ID、对象属性ID、com.vaadin.ui.Component uiContext){
TextField=(TextField)DefaultFieldFactory.get().createField(容器、itemId、propertyId、uiContext);
tField.setImmediate(true);
//…此处的某些代码使用文本字段
if(propertyId.equals(“Foo”)){
组合框选择=新建组合框();
对于(Map.Entry:distinctContainers.entrySet()){
if(entry.getKey().equals(propertyId)){
选择.setContainerDataSource(entry.getValue());
}
}
选择.setImmediate(true);
选择.setItemCaptionPropertyId(propertyId);
select.setItemCaptionMode(AbstractSelect.ITEM\u CAPTION\u MODE\u属性);
返回选择;
}
//…如果为了简洁起见遗漏了Bar和Baz的语句。。。
返回tField;
}
请帮我理解我错过了什么
提前谢谢 从上述异常和代码片段中,我们可以看到需要在
整数
(表示类型)和字符串
(模型)之间进行转换。在这种情况下:
- 表示类型:ItemId={0,1,2}
- 模型:PropertyId的值={“Chris”、“Meg”、“Stewie”}
...
select.setContainerDataSource(entry.getValue());
select.setConverter(new Converter<Object, String>() {
@Override
public String convertToModel(Object itemId, Class<? extends String> paramClass, Locale paramLocale) throws ConversionException {
if (itemId != null) {
IndexedContainer c = (IndexedContainer) entry.getValue();
Object propertyId = c.getContainerPropertyIds().iterator().next();
Object name = c.getItem(itemId).getItemProperty(propertyId).getValue();
return (String) name;
}
return null;
}
@Override
public Object convertToPresentation(String value, Class<? extends Object> paramClass, Locale paramLocale) throws ConversionException {
if (value != null) {
IndexedContainer c = (IndexedContainer) entry.getValue();
Object propertyId = c.getContainerPropertyIds().iterator().next();
for (Object itemId : container.getItemIds()) {
Object name = c.getContainerProperty(itemId, propertyId).getValue();
if (value.equals(name)) {
return itemId;
}
}
}
return null;
}
@Override
public Class<String> getModelType() {
return String.class;
}
@Override
public Class<Object> getPresentationType() {
return Object.class;
}
});
。。。
选择.setContainerDataSource(entry.getValue());
select.setConverter(新转换器(){
@凌驾
公共字符串convertToModel(Object itemId,ClassThank your your your your reply!我使用列表而不是容器作为组合框的输入,返回到一个更“脏”的解决方案。我会在有时间的时候检查这个!
...
select.setContainerDataSource(entry.getValue());
select.setConverter(new Converter<Object, String>() {
@Override
public String convertToModel(Object itemId, Class<? extends String> paramClass, Locale paramLocale) throws ConversionException {
if (itemId != null) {
IndexedContainer c = (IndexedContainer) entry.getValue();
Object propertyId = c.getContainerPropertyIds().iterator().next();
Object name = c.getItem(itemId).getItemProperty(propertyId).getValue();
return (String) name;
}
return null;
}
@Override
public Object convertToPresentation(String value, Class<? extends Object> paramClass, Locale paramLocale) throws ConversionException {
if (value != null) {
IndexedContainer c = (IndexedContainer) entry.getValue();
Object propertyId = c.getContainerPropertyIds().iterator().next();
for (Object itemId : container.getItemIds()) {
Object name = c.getContainerProperty(itemId, propertyId).getValue();
if (value.equals(name)) {
return itemId;
}
}
}
return null;
}
@Override
public Class<String> getModelType() {
return String.class;
}
@Override
public Class<Object> getPresentationType() {
return Object.class;
}
});
select.setConverter(new Converter<Integer, String>());