Cross Validation into Form

Hi, How can I validate data between 2 or more fields into a form ? for example, If I select a state in the combobox state, the combobox city must show only cities from that state.

Or get a date from datebirth field and calculate that into age field.

I’ve seen that we dont have a good and simple way to do that.

How can I implement that ?

I think it could work using Validator Interface but I have no idea how I can refresh others fields values.

add Property.ValueChangeListener to your ‘volatile’ properties.

https://vaadin.com/book/vaadin7/-/page/datamodel.properties.html

Note: in your example use case ( updating age ) make sure you use the Item interface to change your value this will ensure any fields that are bound to that property will display your values.

Also in many cases like this our users did not want to wait for field updates on form/formgroup commit. So I usually ensure the ‘volatile’ fields are set to immediate=true


  textField = new TextField() {
               @Override
                public void setImmediate(boolean immediate) {
                       // ignore value, force true
                       super.setImmediate(true); 
                }
  }

Hi Petrus, thank you for you time! I think I got it but I have a “problem”.

The form is dynamic, it cames from xml or database.

Basically I have a LayoutFactory Class to build the layout and a FieldFactory to build the fields. If there are fields that has a list, so it can be a radio button field, combobox field, checkbox field or other type of list depending your size.

Here you have a piece of code that including the LayoutFactory return into a VerticalLayout.


List<FieldGroupLayout> forms = new ArrayList<>();
VerticalLayout formVL = new VerticalLayout();
for (FieldGroupLayout l : LayoutFactory.createLayouts(model.document.getFieldGroups())) {

	forms.add(l);
	l.addStyleName("form-group");
	formVL.addComponent(l);
	setSpacing(true);

	// doc setting overrides field settings
	if (!model.documentOverview.isEditable()) {
		l.setReadOnly(true);
	}
}

My question is how can I access other field properties into the same context

Thank you !!

To access the other properties of an Item you will need a reference to the Item in the ValueChangeListener .
For example lets say one of the FieldGroups form your example has a field for age, and one has birthDate, they don’t have to be in the same FieldGroup they HAVE to be in the same Item (in this example).


List<FieldGroupLayout> forms = new ArrayList<>();
VerticalLayout formVL = new VerticalLayout();
for (final FieldGroupLayout l : LayoutFactory.createLayouts(model.document.getFieldGroups())) {

    forms.add(l);
    l.addStyleName("form-group");
    formVL.addComponent(l);
    setSpacing(true);

    // doc setting overrides field settings
    if (!model.documentOverview.isEditable()) {
        l.setReadOnly(true);
    }

    // if your FieldGroupLayout does not expose its FieldGroup via a getter it should...
    final FieldGroup fg = l.getFieldGroup();

    // Check if birthDate was bound to a field in this FieldGroup
    if (fg.getBoundPropertyIds().contains("birthDate")) {
         final Field<?> field = fg.getField("birthDate") ;
         if (field != null) { // Should not be null

              // Add change Listener to "birthDate" to update "age"
              field.addValueChangeListener(new Property.ValueChangeListener() {

                  private int calcAge( java.util.Date date) {
                          .....
                  }
 
                  public void valueChange(ValueChangeEvent event) {
                       // Note we can access the original Items property directly from the FieldGroup
                       fg.getItemProperty("age").setValue(calcAge((java.util.Date)event.getProperty().getValue())) ;
                       // That should do the trick. Any field that was bound to "age" should have a ValueChangeListerner registered to its property and thus should now have updated its value..
                  }
            });
         }
    }
}

Let my know if that answers your question .

edit: changed addListener(…) to the Vaadin 7 addValueChangeListener() …

Thank you Petrus, it was that!

All the best
Flávio Santos