How to bind a data model field to multiple components in vaadin 8?

Hi, I have a requirement to represent a model field in different component views. So I did a test, creating two texfields and binding both of them to a bean object Person ‘name’ field, but it seems not working properly.




Person.java


public class Person implements Serializable{
private String title;
private String name;
public Person() {
}
public Person(final String title, final String name) {
this.title = title;
this.name = name;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
System.out.println("Title : " + this.title);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
System.out.println("Name : " + this.name);
}
}




PersonForm.java


public class PersonForm<T extends Person> extends HorizontalLayout{
private TextField nameField1;
private TextField nameField2;
private T person;
private Binder<T> binder;
public PersonForm() {
nameField1 = new TextField("Name1");
nameField2 = new TextField("Name2");
addComponents(nameField1, nameField2);
binder = new Binder<>();
binder.forField(nameField1).bind(Person::getName, Person::setName);
binder.forField(nameField2).bind(Person::getName, Person::setName);
}
public void setPerson(T person) {
this.person = person;
this.binder.setBean(this.person);
}
}




MyUI.java


public class MyUI extends UI {

    @Override
    protected void init(VaadinRequest vaadinRequest) {
    PersonForm<Person> form = new PersonForm<>();
    form.setPerson(new Person("Mr", "Hai Chan"));
        setContent(form);
    }

    @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
    @VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
    public static class MyUIServlet extends VaadinServlet {
    }
}

I was expecting if one textfield value changed, another one value will be changed as well. But it does not work. I am wondering is there any way to use binder to do the consistent update or I have to implement value changed listener.


The attachment is the view snapshot
41003.png

Hi,

Think of each binding as an independent thing when using the
Binder
class. When the user changes the value of an input field, the
Binder
class helps with the binding for that input field only. So you need to update the input fields programmatically. This is pretty straightforward to do. You can add a
ValueChangeListener
to all the fields in the form and update their values using the
Binder.

setBean
method. Binder has an
addValueChangeListener
method for that, so you just need to add one more line to your code:

binder.addValueChangeListener(e -> binder.setBean(person));

Hi, Alejandro,
Thanks for your reply. It seems vaadin does not have “two-way binding”. When I update the data model, it does not refresh the view automatically, need to invoke
readBean
or
setBean
every time the data change. But the view changes will be reflected to the model object by using
setBean
.

There’s no way for the framework to know when you call something like
yourOwnType

.setSomething()
:wink:

I see. Thanks.

I recorded a video about this in case you want to watch it:
https://www.youtube.com/watch?v=4P2BskS_t04

I would like to add to Alejandro Duarte’s anwer:

binder.addValueChangeListener(e -> binder.setBean(person));

You do not even have to be in a scope that knows the person. You can define the ValueChangeListener like this instead:

binder.addValueChangeListener(e -> binder.setBean(binder.getBean()));

PS: I also want to thank Alejandro for the video, I really appreciate those - especially when you explain a little deeper what’s actually happening (3:00 in this video)!

Nice video, Thanks, Alejandro

Alejandro Duarte:
I recorded a video about this in case you want to watch it: https://www.youtube.com/watch?v=4P2BskS_t04

https://vaadin.com/forum/thread/18503943/customize-textfields

help me!!!

help me!!!

Sure, but the link seems to be broken.