Search code examples
vaadin7

Updating after data binding does not update content in UI


Sorry, but I must have a mental lapsus right now, because I don't see where the problem is, and should be trivial. I've prepared a simple scenario where I bind a field to a bean property using the BeanFieldGroup, and when I click the Change and Reset buttons, the model is set with the correct values, but the textfield in the UI is not being updated. I'm using Vaadin4Spring, but should not be the issue.

import com.vaadin.data.fieldgroup.BeanFieldGroup;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener;
import com.vaadin.spring.annotation.SpringView;
import com.vaadin.ui.Button;
import com.vaadin.ui.Notification;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;

import java.io.Serializable;

@SpringView(name = "test")
public class TestView extends VerticalLayout implements View {

    private TextField txtTest = new TextField("Test");
    private Button btnChange = new Button("Click!");
    private Button btnReset = new Button("Reset");

    private TestBean testBean = new TestBean();

    public TestView() {
        txtTest.setImmediate(true);

        addComponent(txtTest);
        addComponent(btnChange);
        addComponent(btnReset);

        BeanFieldGroup<TestBean> binder = new BeanFieldGroup<>(TestBean.class);
        binder.setItemDataSource(testBean);
        binder.setBuffered(false);
        binder.bind(txtTest, "text");

        initComponents();
    }

    private void initComponents() {
        btnChange.addClickListener(new Button.ClickListener() {
            @Override
            public void buttonClick(Button.ClickEvent event) {
                testBean.setText("Hello world!");
            }
        });

        btnReset.addClickListener(new Button.ClickListener() {
            @Override
            public void buttonClick(Button.ClickEvent event) {
                testBean.setText("");
            }
        });
    }

    @Override
    public void enter(ViewChangeListener.ViewChangeEvent event) {
        Notification.show("Test");
    }

    public class TestBean implements Serializable {

        private String text;

        public TestBean() {
            text = "";
        }

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }

    }

}

Solution

  • You are calling a bean setter directly and because Java doesn't provide any way to listen that kind of changes, the Vaadin property (or a TextField) doesn't know that the value has been changed. If you change the value through a Vaadin property by saying

    binder.getItemDataSource().getItemProperty("text").setValue("new value");
    

    then you see "new value" on the TextField, and because buffering is disabled, testBean.getText() also returns "new value".