Binding fields dinamycally is broken in 8 (and other difficulties)

Hi everyone,

i’m trying to migrate entirely a big application to vaadin 8, but i’m encountering a lot of troubles on doing so.
It’s a big application with a lot of dynamical stuff, but i’ll try to stick to the most bugging ones:

  • I haven’t found a way to make the fields required on dependence. Suppose that i have a field asking for a VAT number that is applicable only to companies and not to privates, i need to make it required only if some requirements are met. With vaadin 7 i just used setRequired to switch from true to false, but with the new one i cannot switch once i binded it with asRequired;
  • In order to check if a field is valid, i need to do a complex stack of calls: fieldGroup.getBinding(fieldName).get().validate().isError() insted of just field.IsValid. I ended up doing a function that does only that;
  • I used to have a big hashmap with string key-> Field, that i used to store all the fields available. With this i could easily bind dynamically in vaadin 7, but in 8 i cannot create such map AND use the component to do manual binding. Now i’m committed to a less dynamical way, that i don’t like so much.
  • One last thing: i cannot add and remove validators on the fly. This was very useful.

Could you help me out with some of this point? Expecially the conditional requirement…

Thanks a lot

Alberto

For the first one, could you use two fields, whose visibility you toggle when you know the type of customer? You could even wrap this as a custom composite.

-Olli

I have to agree with Alberto a little bit… Vaadin 8 has made it pretty complex to build and bind fields dynamically. Same goes with creating columns in Grid and dynamically decide how to display the content with ValueProvider at a later step.
Was there a reason to remove the possibility to buildAndBind() like in BeanFieldGroup without replacement?

Thanks for the replies! I’m not sure about the toggling of the visibility since i’m not sure if i can bind mulitple fields to the same property…
If this is feasible i suppose i could do it.
Another way to do it that came to my mind is to add event listeners to the validators and enable / disable them via eventbus…

One thing i’d like to point out is that i have to rethink the application majorly, and this is not that good.

You can bind multiple fields to the same property - I just tested it out to make sure. Something like this:

        Bean bean = new Bean();

        Binder<Bean> binder = new Binder<>();
        binder.setBean(bean);

        TextField tf = new TextField();
        binder.forField(tf).bind(Bean::getName, Bean::setName);

        TextField tf2 = new TextField();
        binder.forField(tf2).bind(Bean::getName, Bean::setName);

        Button button = new Button("check", e -> {
            Notification.show("bean.name=" +bean.name);
        });

-Olli

Well, that works but it’s not feasible. Suppose i have with the required option and the other without. Even if i hide one it’s still going to be required…

I have to think a workaround or go back to 7.

No, I don’t think a hidden field will be required. It’s not even in the DOM at that point.

-Olli


@Alberto
: we have a similar situation here. A large project with lot dynamic objects controlled by repository metadata. We did not find any way how to migrate from Vaadin 7 to 8. A lot of APIs were sacrificed in favor of easy beans handling. If your data are not encapsulated in beans, if your field types are not known at design time and you need to use AbstractField, if you need to add/remove features like converters, validators, visibility etc. dynamically in runtime, you probably have to rewrite large parts of your framework. We decided to stay with Vaadin7.

Same here. I wrote a proposal in https://github.com/vaadin/framework/issues/9949 as to how to remedy some of the most annoying problems with the new data binding API. Allowing modifications to the binding could also fix another portion of the problem. As Robert above said, the solution adopted in Vaadin 8 was a sacrifice when it didn’t have to be one - just exposing some additional methods would allow Vaadin 8 to be friendly to dynamic forms while keeping all the existing functionality intact.

I am having similar problems here. Please, could you clarify what is the best practice for handling these situations. For example, how to dinamically change the required validation of a field when another related field is changed by the user. I can’t accept that having two fields (required/not required) is the framework solution.

I have seen some push requests from Piotr being accepted in 8.2.Alpha2 that seems to go in the right way. Does this version allow removing/Adding validators?

I was looking for a posting on the missing FieldFactory on the new Vaadin 8 Binder, to replace the similar FieldFactory in FieldGroup, and this seems to be close enough: in other words, when the developers at Vaadin designed a new API, did they review the existing use cases of the previous major version?
I am trying to convert a very large application that relies heavily on build factories and grids with runtime generated columns, both use cases discussed in this thread I believe, and I find both very challenging to replace on Vaadin 8.
Reuben

I think that at least for the required field issue you could just create a custom validator, which in the validation method (apply) checks the status of the field (f1), on which the validated field (f2) is dependent on, and acts accordingly, e.g.

binder.forField(f1).bind(s -> v1, (s, input) -> v1 = input); binder.forField(f2).withValidator((value,context) -> { if (f1.getValue().equals("not okay") && (value == null || value.isEmpty())) { return ValidationResult.error("f2 required"); } return ValidationResult.ok(); }).bind(s -> v2 , (s, input) -> v2 = input); f1.addValueChangeListener(l -> binder.validate()); You just also need to listen for the value change events of f1 to get the visuals immediately (by calling binder.validate()). This doesn’t obviously add the red asterisk that required fields usually have, but that is a property of the f2 component, not the validator, so it could be set according to the value of f1 in the event handler or the validator in this case.

  • Katri