BeanFieldGroup and Two Way Binding?

Hi guys, I have a small question on FieldGroup and binding data to it. First of all I come from the Adobe Flex world where data binding is pretty powerful, especially two way data binding. Basically, I am looking for a way to do two way binding in Vaadin. Below I have a small sample of code that has a Person Model and a FieldGroup which are bound. The form gets bound correctly meaning if I make a change using the UI, the model reflects the change, but I am looking for a way where I can just update the backing model class directly and have the UI reflect those changes.

See my comments in the button clickhandler below for my attempts at this.

Example Form Binding:


    Person person = new Person("Dan");
    BeanFieldGroup<Person> fieldGroup = new BeanFieldGroup<Person>(Person.class);

    @Override
    protected void init(VaadinRequest request) {
        final FormLayout layout = new FormLayout();
        setContent(layout);

        final TextField nameTextField = new TextField("Name:");
        layout.addComponent(nameTextField);
        layout.addComponent(new Button("Update Name", new Button.ClickListener() {
            @Override
            public void buttonClick(ClickEvent event) {
                //1st try at updating the TextField to display "Bob"
                //person.setName("Bob"); //doesn't work - I guess it's not magic :)

                //2nd try which I thought would work, but doesn't
                //BeanItem<Person> personBeanItem = fieldGroup.getItemDataSource();
                //personBeanItem.getItemProperty("name").setValue("Bob");

                //3rd try which works by directly setting value on the actual text field, but I am trying to avoid this
                nameTextField.setValue("Bob");
            }
        }));

        fieldGroup.setItemDataSource(person);
        fieldGroup.bind(nameTextField, "name");
    }

Person Class:


public class Person {

    String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

Thanks and I appreciate anyone setting me straight.
-Dan

Have a look at this gist maybe it would help you.


Snippet from my Fieldgroup use

Your 2nd try should also work - I didn’t see immediately what would be wrong with it, the approach should work.
Just in case, check that you get the correct BeanItem instance (whose properties the fields are listening to) etc.

Thanks Christian and Henri for the suggestions. I finally got the 2nd try working by turning off buffering on the fieldGroup. Two way binding for the win!!!
See my highlighted change below. The only downside I see now of turning off buffering is that now the fieldGroup.isModified() function always returns false :frowning:

The reason that I am after this two way binding functionality, is that our team is attempting to use the presentation model for our views which would be very similar to what we do in our Adobe Flex applications. With the presentation model class not having any reference to the view, it makes it really easy to test.

Now I want to see if I can take this binding approach to something other then forms, lets say bind some view element’s visible property to some backing presentation model property.


 @Override
    protected void init(VaadinRequest request) {
        final FormLayout layout = new FormLayout();
        setContent(layout);

        final TextField nameTextField = new TextField("Name:");
        layout.addComponent(nameTextField);
        layout.addComponent(new Button("Update Name", new Button.ClickListener() {
            @Override
            public void buttonClick(ClickEvent event) {
                //1st try at updating the TextField to display "Bob"
                //person.setName("Bob"); //doesn't work - I guess it's not magic 

                //2nd try now works with buffering turned off
                BeanItem<Person> personBeanItem = fieldGroup.getItemDataSource();
                personBeanItem.getItemProperty("name").setValue("Bob");

                //3rd try which works by directly setting value on the actual text field, but I am trying to avoid this
                //nameTextField.setValue("Bob");
            }
        }));

        fieldGroup.setBuffered(false); [color=#fc0404]
//<------------- Turned off buffering
[/color]
        fieldGroup.setItemDataSource(person);
        fieldGroup.bind(nameTextField, "name");
    }