ValueChangeListener and DataBinding

Hi Guys,
currently our company decided to switch all our applications from JSF to Vaadin. It was a good move until we discovered couple of bad design decisions. It’s probably because of legacy architecture but still…

  1. If the field is in readOnly or disabled or not visible (even worse) state why validators (for example required field) are still fired? They shouldn’t fire because user can’t change or add any value to those fields (UI components) .
    But I can live with this. I can make this validation before commit and that’s it. But that makes required property unusable all our applications.

  2. The worst problem that we found (and because of this, we are questioning our decision) is that ValueChangeListeners are fired every time when binding is happening. In other words when a value is assigned trough setPropertyDataSource from backing bean to the component. Why? Is there any way to distinguish when the user changed a value on a component (for example changed a value on ComboBox) comparing to databinding assignment. The reason is very simple. We want to fire some changes in the values of other fields ONLY when user changed the value of the field. This is something common in JSF binding, and valuechangelisteners are fired only after user interaction and not when you assign a new binding to the field. If there is a way to distinguish user interaction changes compared to the databinding changes (in Vaadin it’s all ValueChangeEvent). Looking at the AbstractField I see that method “fireDataChange” method is called on too many places (on getValue, setValue, setPropertyDataSource, discard, …).

Thank you for your answer in advance…

Best regards

Regarding number 2, it is simply a design decision the development team made waaay back (something like 2002 propably). There is no way to ask Vaadin for the origin of the event, but you can still detect it yourself quite easily:

private boolean maskValueChange=false;

public void initData() {
    maskValueChange=true;
    //init data
    maskValueChange=false;
}

public void valueChanged(VCE event) {
    if(maskValueChange) return;
    //handle user input
}

Yes but still ValueChangeListener is fired on form commit. So it doesn’t work in this way also.
The problem is that we use ValueChangeListener for altering fill out some fields triggered by changes of another field. This changes should be made only if the user changed the value. For example:

Let’s say we have 4 fields in the form (actually there are more then 180 in the application !!!).

If we change the value of the combobox on field 1, field 2 and field 3 should get some values depending of the selected value of field 1. So far so good. But, the user can after that change the values of field 2 and 3. That means, fields 2 and 3 should be overridden “ONLY” if the user changed the value of field 1, in all other cases fields should remain the same as was. The problem is that those fields are always overwritten because of the valuechangelistener firing on initial databinding, user interaction with the component and on form commit.

We are trying right now to use valuechangelistener on MethodProperty and NestedMethodProperty to see if there will be possible to achieve this functionality.

Any other suggestion will be appreciated.

I don’t see a problem with what you described: by masking all programmatic valuechanges, you effectively reduce the value change events to those times that the actually come from the user. You just need to remember to change the mask value everywhere you might invoke the setter, which includes the commit() method.

I am also facing 2 point , any best solution ?

The same for me on 2.

Worst part is that converter is (probably) not already prepared, so when I call

(Long) field.getConvertedValue(); I get ClassCastException - String cannot be cast to Long.

Although that happened before my time at Vaadin, I think I can explain why value change events are sent for all changes: Vaadin fields also implement Property, and can be used as data sources for other fields. Thus, to make those fields update correctly, all changes must trigger events. This was long before the current Converter mechanism was implemented.

I agree it would be useful for the events to have a flag indicating whether the change was made by a user. There are some old tickets that suggest such a mechanism or variants thereof:
#8635
(add information about whether the event was client or server initiated),
#9070
(disable events - not sure if really feasible without breaking a lot of applications).

Old thread but I just has same problem as Luka, here is my solution:
in formInit()

vcMask = true; fieldGroup.bindMemberFields(this); vcMask = false; and in listener:

field.addValueChangeListener(valueChange -> { if(vcMask) return; ... }); Greetings, Marek

HI Marek,

thanks for yor response , you can overide the component and controle the fire even if you have written as generic component , i have fixed that issue too. thanks once again.

It’s not funny when you are creating a huge ERP system. That’s was a decision mistake for one of our huge project (insurance company system). Imagine that only one window has more then 150 data components (Input fields, combo boxes, …) and there are many different windows. It is a pity, because it has huge potential but fails in 3 important features:

  1. This topic (value change event)
  2. Speed of rendering components on client side
  3. Out of sync problem
    Now we swiched back to JSF.
    I still think that Vaadin has better UI control than any JSF framework especialy for generic form generation and all benefits that you can’t have with declarative UI definition (in easy way).

Hi Luka,

I am doing a evaluation of Primefaces and Vaadin for generic form generation.

We have a data driven application and based on model values the UI is to be generated (model includes values for the attributes default value, render, disabled and readonly).

I was able to do a generic form generation in JSF / Primefaces using programmatically add component where we had placeholder like a panel component in the xhtml page. We had a custom ELResolver to resovle the values for the page.

I assumed this should have been simple with vaadin , but now I am stuck since only the value gets binding when using the setPropertyDataSource. The Components are added directly using addComponent(component) and are not declared as instance variable in a View. On value change of a componet, I don’t have control over the attribute’s like read only, disabled , visible / render of other dependent components and the components do not update based on the model value.

Do you have any suggestion if you encountered a similar case?

Ravi

Hi,
I am using vaadin-combo-box in Angular 2 as below inside “ngFor”.

<vaadin-combo-box label=“Role Name” [items]
=“roles” item-label-path=“Name” item-value-path=“ID” [(value)]
=“roleSkill.RoleId” required error-message=“Role is required” (value-changed)=“resetValues(rowIndex)”>

But, while binding the control from “ngOnInit” of the component, the “value-changed” event of the combo box is also getting executed, which is resulting the values to be reset.

Quick resposne would be greatly appriciated. Thanks in advance.

Sadly, Vaadin is plagued with poor design decisions.

I’ve also waisted several hours because of ValueChangedEvent being fired when the value was set programmatically (either by binding or by calling setValue() on the field).
To make matters worse, it behaved differently on my laptop and on the staging environment (!?).
(It looks as if the binding and the setting of the listener are not synchronized.)

I had to resort to code like this:

[code]

        @Override
        public void valueChange(ValueChangeEvent event) {
            Double newValue = (Double) myField.getConvertedValue();
            if (!Objects.equals(entity.getMyValue(), newValue)) {
                entity.setMyValue(newValue);
                updateOtherObjects();
            }
        }

[/code]The ValueChangeEvent class is not very helpful, frankly.
It could provide an event type (user, program, …) or the old and new values. It only provides the changed property which can be accessed from the field itself anyway.

Hi Agustí,

Vaadin 8 provides the isUserOriginated flag, maybe this is something that will help? See
https://github.com/vaadin/framework/blob/master/server/src/main/java/com/vaadin/data/HasValue.java#L126

-Olli