Binder returns null

I created a form layout with binder.

public class AddressForm {

    private ComboBox<AddressType> addressType = new ComboBox<>("Address Type");
    private TextField doorNo = new TextField("Door No");
    private TextField street = new TextField("Street");
    private TextField city = new TextField("City");
    private TextField state = new TextField("State");
    private ComboBox<Country> country = new ComboBox<>("Country");
    private EmailField email = new EmailField("Email");
    private TextField phoneNumber = new TextField("Phone Number");
    private TextField mobileNumber = new TextField("Mobile Number");
    private Binder<Address> binder = new BeanValidationBinder<>(Address.class);


    public AddressForm() {

        customizeFields();
        binder.bindInstanceFields(this);
    }

    public AddressForm(AddressType addressType, Country country) {
        this();
        this.addressType.setValue(addressType);
        this.country.setValue(country);
    }

    public static AddressForm of(AddressType addressType, Country country) {
        return new AddressForm(addressType, country);
    }

    private void customizeFields() {
        addressType.setItemLabelGenerator(addressType1 -> addressType1.name());
        addressType.setItems(AddressType.values());
        country.setItemLabelGenerator(country1 -> country1.name());
        country.setItems(Country.values());
    }

    public FormLayout fullForm() {
        return Components.formLayout()
                .add(addressType,2)
                .add(doorNo,street,city,state,country,email,phoneNumber,mobileNumber)
                .build();
    }

    public void setAddress(Address address) {
        binder.setBean(address);
    }

    public Address getAddress() {
        return binder.getBean();
    }
}


Now,when I try to get getAddress(), the address is null though I set the address type already. How to get the address now ?

You need to invoke this method at least once.

I thought the binder keeps tracks of the field changes so it knows there is a field value already set and so it would give me the Address with that first value set

Any doc/blog post which explains usages of all of these and their differences ( when to use what and in what order )

setBean()
readBean()
getBean()
writeBean()

That would help. I used to have a different library which has only setValue and getValue for formLayout ( that lib is out of date now ) so moving to vaadin core APIs

Binder is “bean first” - so without a bean / dto there is nothing to store the selected values.

You have the wrong idea here. Instead of setting the default values to the fields, you apply the defaults to your bean and afterwards use set/read to apply the bean and its values to the field and keep track of those. (Note: this only applies to the bean when read/set is called - once a bean is applied and you want to change values and reflect those also to your field: either use read/set again or simply add the value to the field and let the field sync them to their bean’s field (with setBean))

I understood this but partially. I see still binder is not picking up the field value changes. Here is how I create the form and set the address

private AddressForm createAddressForm(AddressType addressType, Country country) {
        Address address = new Address();
        address.setAddressType(addressType);
        address.setCountry(country);
        AddressForm addressForm = AddressForm.create();
        addressForm.setAddress(address);
        return addressForm;
    }

Now, when I change any other field value in the UI, the binder is still not getting updated and shows null values for those modified on the UI. What am I missing again ?

As per this link, there are two types of binding. Manual ( read/write Bean) and Automatic ( set/get bean). So, that is the difference and I can use either of them as I need ?

Looks correct, only thing hard to check (because we can’t see it); how are you using that method and are all fields matching the values of the bean?

Here setBean() worked but not the readBean() because getFormValue() returns null. So, something is different and that’s what confusing here. Which method to use and when ?
image

Both work as expected. Did you take the time and read their JavaDocs?

readBean does not associate the Bean with the Binder; therefore getBean is null. If you want to access the bean from the Binder you need setBean.

Personally I prefer setBean over readBean, but there are circumstances where it could create problems if the underlying Bean has for example some weird side effects when setXyz is called because those can happen quite often within the binders internal logic.

Without getBean() how do I get back the value from the form?

writeBean while passing your address to it - it writes the values to it or throws if an error occurred

Let me put my lack of understanding here. I created a formlayout with binder. Now when the user entered some values in the form, which method should I use to get his values ?

Use

  • getBean if you used setBean
  • writeBean if you used readBean (and keep track of the bean / object yourself)