Bas*_*que 7 java data-binding vaadin vaadin8
使用Vaadin 8 @PropertyId注释Binder::bindInstanceFields肯定比为每个字段属性绑定编写一行代码更短更甜.
Person person; // `name` is String, `yearOfBirth` is Integer.
…
@PropertyId ( "name" )
final TextField nameField = new TextField ( "Full name:" ); // Bean property.
@PropertyId ( "yearOfBirth" )
final TextField yearOfBirthField = new TextField ( "Year of Birth:" ); // Bean property.
…
// Binding
Binder < Person > binder = new Binder <> ( Person.class );
binder.bindInstanceFields ( this );
binder.setBean ( person );
Run Code Online (Sandbox Code Playgroud)
但是我们得到一个异常抛出,因为yearOfBirth属性是一个整数,这种简单的绑定方法缺少转换器.
严重:
java.lang.IllegalStateException:属性类型'java.lang.Integer'与字段类型'java.lang.String'不匹配.应使用转换器手动配置绑定.
这是否意味着Binder::bindInstanceFields只能使用完全由String数据类型属性构成的bean ?
有没有办法指定一个Converter这样的,StringToIntegerConverter而不必逐条列出代码中的每一个绑定?
请参阅Vaadin框架,Vaadin数据模型,将数据绑定到表单:
转换
您还可以将应用程序数据绑定到UI字段组件,即使类型不匹配也是如此.
Binder#bindInstanceFields() 说:
并不总是可以将字段绑定到属性,因为它们的类型不兼容.例如,自定义转换器需要绑定
HasValue<String>和Integer属性(这将是"年龄"属性的情况).除非在调用方法之前手动配置了字段,否则IllegalStateException将抛出此类情况.bindInstanceFields(Object)[...]:该
bindInstanceFields(Object)方法不会覆盖现有绑定.
[由我强调.]
所以,AFAIU,这应该工作:
private final TextField siblingsCount = new TextField( "? of Siblings" );
...
binder.forField( siblingsCount )
.withNullRepresentation( "" )
.withConverter(
new StringToIntegerConverter( Integer.valueOf( 0 ), "integers only" ) )
.bind( Child::getSiblingsCount, Child::setSiblingsCount );
binder.bindInstanceFields( this );
Run Code Online (Sandbox Code Playgroud)
但它仍然抛出:
java.lang.IllegalStateException: Property type 'java.lang.Integer' doesn't match the field type 'java.lang.String'. Binding should be configured manually using converter. ... at com.vaadin.data.Binder.bindInstanceFields(Binder.java:2135) ...
你在跟我开玩笑吗?这就是我做的,不是吗?我更怀疑"不会覆盖现有的绑定".或者,如果实际上没有被覆盖,那么它们似乎bindInstanceFields()至少被忽略了.
相同的手动绑定配置在不使用时工作,Binder#bindInstanceFields()但对每个字段使用单独绑定的方法.
另请参阅线程Binding from Integer不在 Vaadin Framework数据绑定论坛中工作,问题#8858 Binder.bindInstanceFields()覆盖现有绑定.
比@ cfrick的回答更简单:
/** Used for workaround for Vaadin issue #8858
* 'Binder.bindInstanceFields() overwrites existing bindings'
* https://github.com/vaadin/framework/issues/8858
*/
private final Map<String, Component> manualBoundComponents = new HashMap<>();
...
// Commented here and declared local below for workaround for Vaadin issue #8858
//private final TextField siblingsCount = new TextField( "? of Siblings" );
...
public ChildView() {
...
// Workaround for Vaadin issue #8858
// Declared local here to prevent processing by Binder#bindInstanceFields()
final TextField siblingsCount = new TextField( "? of Siblings" );
manualBoundComponents.put( "siblingsCount", siblingsCount );
binder.forField( siblingsCount )
.withNullRepresentation( "" )
.withConverter( new StringToIntegerConverter( Integer.valueOf( 0 ), "integers only" ) )
.bind( Child::getSiblingsCount, Child::setSiblingsCount );
binder.bindInstanceFields( this );
...
// Workaround for Vaadin issue #8858
addComponent( manualBoundComponents.get( "siblingsCount" ) );
//addComponent( siblingsCount );
...
}
Run Code Online (Sandbox Code Playgroud)
修复#8998使bindInstanceFields不绑定已使用函数绑定的字段.
该修补程序的源代码至少出现在Vaadin 8.1.0 alpha 4预发行版(或许还有其他版本)中.
Basil Bourque更新......
您的想法,如上所示,Binder::bindInstanceFields在非兼容(整数)属性的手动绑定后使用确实似乎对我有用.您抱怨说,在您的实验代码中,调用Binder::bindInstanceFields未能遵循记录的行为,其中调用"不会覆盖现有绑定".
但它似乎对我有用.这是Vaadin 8.1.0 alpha 3的示例应用程序.首先,我手动绑定yearOfBirth属性.然后我binder.bindInstanceFields用来绑定带@PropertyId注释的name属性.两个属性的字段将显示为已填充并响应用户编辑.
我是否遗漏了某些东西,或者这是否记录在案?如果我犯了错误,请删除此部分.
package com.example.vaadin.ex_formatinteger;
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.data.Binder;
import com.vaadin.data.converter.StringToIntegerConverter;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.*;
import javax.servlet.annotation.WebServlet;
/**
* This UI is the application entry point. A UI may either represent a browser window
* (or tab) or some part of a html page where a Vaadin application is embedded.
* <p>
* The UI is initialized using {@link #init(VaadinRequest)}. This method is intended to be
* overridden to add component to the user interface and initialize non-component functionality.
*/
@Theme ( "mytheme" )
public class MyUI extends UI {
Person person;
//@PropertyId ( "honorific" )
final TextField honorific = new TextField ( "Honorific:" ); // Bean property.
//@PropertyId ( "name" )
final TextField name = new TextField ( "Full name:" ); // Bean property.
// Manually bind property to field.
final TextField yearOfBirthField = new TextField ( "Year of Birth:" ); // Bean property.
final Label spillTheBeanLabel = new Label ( ); // Debug. Not a property.
@Override
protected void init ( VaadinRequest vaadinRequest ) {
this.person = new Person ( "Ms.", "Margaret Hamilton", Integer.valueOf ( 1936 ) );
Button button = new Button ( "Spill" );
button.addClickListener ( ( Button.ClickEvent e ) -> {
spillTheBeanLabel.setValue ( person.toString ( ) );
} );
// Binding
Binder < Person > binder = new Binder <> ( Person.class );
binder.forField ( this.yearOfBirthField )
.withNullRepresentation ( "" )
.withConverter ( new StringToIntegerConverter ( Integer.valueOf ( 0 ), "integers only" ) )
.bind ( Person:: getYearOfBirth, Person:: setYearOfBirth );
binder.bindInstanceFields ( this );
binder.setBean ( person );
setContent ( new VerticalLayout ( honorific, name, yearOfBirthField, button, spillTheBeanLabel ) );
}
@WebServlet ( urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true )
@VaadinServletConfiguration ( ui = MyUI.class, productionMode = false )
public static class MyUIServlet extends VaadinServlet {
}
}
Run Code Online (Sandbox Code Playgroud)
简单的Person课程.
package com.example.vaadin.ex_formatinteger;
import java.time.LocalDate;
import java.time.ZoneId;
/**
* Created by Basil Bourque on 2017-03-31.
*/
public class Person {
private String honorific ;
private String name;
private Integer yearOfBirth;
// Constructor
public Person ( String honorificArg , String nameArg , Integer yearOfBirthArg ) {
this.honorific = honorificArg;
this.name = nameArg;
this.yearOfBirth = yearOfBirthArg;
}
public String getHonorific ( ) {
return honorific;
}
public void setHonorific ( String honorific ) {
this.honorific = honorific;
}
// name property
public String getName ( ) {
return name;
}
public void setName ( String nameArg ) {
this.name = nameArg;
}
// yearOfBirth property
public Integer getYearOfBirth ( ) {
return yearOfBirth;
}
public void setYearOfBirth ( Integer yearOfBirth ) {
this.yearOfBirth = yearOfBirth;
}
// age property. Calculated, so getter only, no setter.
public Integer getAge ( ) {
int age = ( LocalDate.now ( ZoneId.systemDefault ( ) )
.getYear ( ) - this.yearOfBirth );
return age;
}
@Override
public String toString ( ) {
return "Person{ " +
"honorific='" + this.getHonorific () + '\'' +
", name='" + this.getName () +
", yearOfBirth=" + this.yearOfBirth +
", age=" + this.getAge () +
" }";
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5023 次 |
| 最近记录: |