有没有办法在可编辑的 Vaadin 8 网格中设置验证和编辑长值
Is there a way to set a validation and edit a long value in an editable Vaadin 8 Grid
我有一个 Vaadin 8 网格,我想在其中将一列设置为可编辑。为此,我有 Food.calories
是 long 的地方(是的,在这种情况下它可能是 int 但请记住,这是一个示例,我的特定用例需要 long):
Binder<Food> binder = foodGrid.getEditor().getBinder();
TextField caloriesTextField = new TextField();
binder.forField(caloriesTextField)
.withValidator(CustomCaloryValidator::isValidValue, "Must be valid a positive amount")
.withConverter(new StringToCaloriesConverter("Must be an integer"))
.bind(Food::getCalories, Food::setCalories);
// This line fails with the error because the types do not match.
foodGrid.addColumn(Food::getCalories, new NumberRenderer(myNumberFormat))
.setEditorComponent(new TextField(), Food::setCalories);
不幸的是,这不起作用并出现以下错误:
类型参数 'C' 的推断类型 'C' 不在其范围内;应该实施 'com.vaadin.data.HasValue'
我到处寻找,但除了简单的编辑之外,找不到任何例子。 demo sampler 确实有一个使用滑块的更复杂的示例,但我不知道如何从该示例中推断...
我明白这个错误,它正在尝试将 long 映射到 String。但是我找不到向 addColumn 添加转换器以使其工作的方法...
首先主要问题是Binder没有指定泛型类型,需要是:
Binder<Food> binder = foodGrid.getEditor().getBinder();
而不是:
Binder binder = foodGrid.getEditor().getBinder();
也就是说还有其他几个问题。首先,当您执行 forField()
时,您需要跟踪该绑定,以便稍后使用该列进行设置。这对我来说一点都不清楚。具体来说,您需要:
Binder.Binding<Food, Long> caloriesBinder = binder.forField(caloriesTextField)
.withValidator(CustomCaloryValidator::isValidValue, "Must be valid a positive amount")
.withConverter(new StringToCaloriesConverter("Must be an integer"))
.bind(Food::getCalories, Food::setCalories);
我不是 100% 确定 caloriesBinder,因为我的代码不同,这是一个示例,但您需要该绑定。然后你接受那个绑定并做:
foodGrid.getColumn("calories").setEditorBinding(caloriesBinding);
这允许正确的编辑器工作。这在文档中,但示例非常简单,所以我错过了。
下一步非常重要,具体取决于您要显示的内容,即添加渲染器,否则您可能 运行 遇到一些奇怪的问题。例如,如果您使用 long 来存储货币,那么您需要将其转换为显示货币金额。同样,如果您使用的是日期,那么您可能还想对其进行格式化。然后你需要添加一个渲染器。我能找到没有编译错误(类型不匹配)的唯一方法是:
((Grid.Column<Food, Long>)foodGrid.getColumn("calories")).setRenderer(new CaloriesRenderer());
为了完整起见,您需要启用编辑器:
foodGrid.getEditor().setEnabled(true);
最后,如果 table 是更大 bean 的一部分,那么您需要调用 foodGrid.setItems()
,您不能只依赖 binder.readBean()
,因为它不能接受列表。因此,例如,如果豆子不是食物而是包含多种成分的一餐,那么你不能做 binder.readBean(meal)
也不能做 binder.readBean(meal.getIngredients)
即使你可以做 binder.readBean(meal)
表格的其余部分。我能让它工作的唯一方法是:
binder.readBean(meal);
foodGrid.setItems(meal.getIngredients);
我有一个 Vaadin 8 网格,我想在其中将一列设置为可编辑。为此,我有 Food.calories
是 long 的地方(是的,在这种情况下它可能是 int 但请记住,这是一个示例,我的特定用例需要 long):
Binder<Food> binder = foodGrid.getEditor().getBinder();
TextField caloriesTextField = new TextField();
binder.forField(caloriesTextField)
.withValidator(CustomCaloryValidator::isValidValue, "Must be valid a positive amount")
.withConverter(new StringToCaloriesConverter("Must be an integer"))
.bind(Food::getCalories, Food::setCalories);
// This line fails with the error because the types do not match.
foodGrid.addColumn(Food::getCalories, new NumberRenderer(myNumberFormat))
.setEditorComponent(new TextField(), Food::setCalories);
不幸的是,这不起作用并出现以下错误:
类型参数 'C' 的推断类型 'C' 不在其范围内;应该实施 'com.vaadin.data.HasValue'
我到处寻找,但除了简单的编辑之外,找不到任何例子。 demo sampler 确实有一个使用滑块的更复杂的示例,但我不知道如何从该示例中推断...
我明白这个错误,它正在尝试将 long 映射到 String。但是我找不到向 addColumn 添加转换器以使其工作的方法...
首先主要问题是Binder没有指定泛型类型,需要是:
Binder<Food> binder = foodGrid.getEditor().getBinder();
而不是:
Binder binder = foodGrid.getEditor().getBinder();
也就是说还有其他几个问题。首先,当您执行 forField()
时,您需要跟踪该绑定,以便稍后使用该列进行设置。这对我来说一点都不清楚。具体来说,您需要:
Binder.Binding<Food, Long> caloriesBinder = binder.forField(caloriesTextField)
.withValidator(CustomCaloryValidator::isValidValue, "Must be valid a positive amount")
.withConverter(new StringToCaloriesConverter("Must be an integer"))
.bind(Food::getCalories, Food::setCalories);
我不是 100% 确定 caloriesBinder,因为我的代码不同,这是一个示例,但您需要该绑定。然后你接受那个绑定并做:
foodGrid.getColumn("calories").setEditorBinding(caloriesBinding);
这允许正确的编辑器工作。这在文档中,但示例非常简单,所以我错过了。
下一步非常重要,具体取决于您要显示的内容,即添加渲染器,否则您可能 运行 遇到一些奇怪的问题。例如,如果您使用 long 来存储货币,那么您需要将其转换为显示货币金额。同样,如果您使用的是日期,那么您可能还想对其进行格式化。然后你需要添加一个渲染器。我能找到没有编译错误(类型不匹配)的唯一方法是:
((Grid.Column<Food, Long>)foodGrid.getColumn("calories")).setRenderer(new CaloriesRenderer());
为了完整起见,您需要启用编辑器:
foodGrid.getEditor().setEnabled(true);
最后,如果 table 是更大 bean 的一部分,那么您需要调用 foodGrid.setItems()
,您不能只依赖 binder.readBean()
,因为它不能接受列表。因此,例如,如果豆子不是食物而是包含多种成分的一餐,那么你不能做 binder.readBean(meal)
也不能做 binder.readBean(meal.getIngredients)
即使你可以做 binder.readBean(meal)
表格的其余部分。我能让它工作的唯一方法是:
binder.readBean(meal);
foodGrid.setItems(meal.getIngredients);