Hi, i have a general question regarding data binding.
I dont understand why one should use all that FieldGroup stuff (except maybe because of validation/buffering), can someone explain me that?
Assume i have a TextField and i add a value change listener, and i want if a change occurs, my POJO being updated on a special field. When using a FieldGroup i may save some lines of code, i dont have to implement the listener which sets pojo.setValue(event.getSource()…) but thats not all, isnt it?
Because i am wondering if i understood it correctly with binding data to a pojo. https://github.com/olze/cms/blob/develop/src/main/java/ch/trustserv/mycms/Installation.java - when i execute System.out.println(binder.getField(“password”).getValue()); in the listener it works and i get the value, but why should i not simply use a final DatasourceProperties (my pojo which holds information about the database config) and write to that when a value change occured? The only useful reason to use the FieldGroup would be to use the commit() feature and do some validation.
A very good question, FieldGroups essential functionality is often hidden behind less essential features. And as you had figured out, its main job is to avoid boilerplate code when binding data from your model to your UI fields. I’m practically never using e.g. buffering or the raw FieldGroup (that works with Vaadin’s low level “proprietary” Item-Property interfaces).
Instead I’d always suggest to have clean entity objects/pojos/DTOs that you bind to your UI using BeanFieldGroup. Then you can by just naming convention (or alternatively using annotation) bind UI inputs to their counterpart in you domain model. You could of course do this manually as well, but that looks bad in your code (DRY). You can also easily hook in some validators that you can check before sending your update pojo back to your “backend”. BeanFieldGroup supports bean validation api out of the box, so with annotations in the model you’ll automatically get a basic validation to your UI layer.
I’m also most often using some sort of abstract form class that helps me bit further with databinding. This way I also get e.g. save/cancel/reset buttons really easily. The
Viritin add-on contains a nice helper class called AbstractForm.
Check out e.g.
this JPA-Addressbook example app . Although you wouldn’t use JPA, the application usise uses BeanFieldGroup via an abstract form class, in the way most developers should do it.
I get started pretty quick with the form and it looks nice, but what i am now really missing is some kind of JavaDoc. Does this exist? Sorry i am new to Vaadin and the addons, no idea where to search for that. At the moment i just read code and try to see what is possible.
For example, my save/reset buttons are now at top of the form and not (what i was expecting) at the bottom.
Check the createContent method. save/reset/delete buttons are in toolbar, so just move that couple of lines down to be after your form fields. Check the
related source in the example .
There should indeed be better javadocs AND some sort of tutorial. I’m glad you made a nice start with it, but for many beginner programmers it would be essential the have some sort of step by step tutorials. The github wiki would probably be the right place for that, if you want to participate, just let me know.
Of course i would like to help if i can. I get stuck on many things which are probably absolutly logical for someone who works with such stuff all day, but for example the POJO must have getters and setters, otherwise validation is not possible and the field is not editable. Also, i am missing somehow the annotation to map a field X to the form TextField Y.
Using AbstractForm, I noticed that on a fresh load of the form, the Save button is not disabled by default. It is clickable just fine, even though I’ve a field in my POJO annotated NotNull. The Save button works even though the NotNull field is empty.
One would expect the Save button to be disabled by default until all validations are passed. Perhaps I’m missing something?
Essentially, I expect that the save button shouldn’t work at all on a fresh load of the form until all validations have passed.
Using Viritin 1.29 on Payara Server 4.1 and Java EE7 on Fedora 21 x64 if that helps
EDIT
As work around, I disable the save button in the Enter method of the View in which I’m inserting the form, and enabling it in the validityChangedListener method, only if
event.getComponent.isValid()
returns true.
Used to use the raw FieldGroup/BeanFieldGroup line. But they involved writing copious amounts of code to get them working. I find the AbstractForm from the Viritin library for instance, very very helpful.
Seraaj, that is probably a regression due to some refactoring I did a while ago. I was able to reproduce in the proejcts PersonTest although in my typical applications it worked just fine. It should be now
fixed . It would be helpful if you could test the snapshot version 30-SNAPSHOT. I pushed it here for testing (or you can build a fresh version locally):
<repository>
<id>viritin</id>
<url>http://virit.in/maven2</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
cheers,
matti
Great. Save button is disabled by default. However, the delete button isn’t. I’ve a case where one needs to fill certain mandator fields before deleting an entity. Now when I set up a delete form and show it to the user, even with this snapshot, the delte button is still enabled by default albeit the validations available in the backing entity.
Again to confirm, the save button is disabled by default until all validations are passed.
I think that is domain specific feature, and I’d like to keep the default like this. But it should be pretty easy to change the behavior by adding a ValidityChangedListener to your AbstractForm and then modifying the delete button programmatically there. Let me know if this don’t work.
Could you please let me know how to bind the nested entity in the AbstractForm?
I have 2 entities, Entity1 and Entity2 is reference in Entity1. I have created AbstractForm class for Form and setEntity(Entity1) is just binding the primitive member fields of Entity1.
Could you please help me resolve this issue? Thanks.
So you have have one form that edits e.g. user.firstName and user.address.city fields? Instead of presenting fields at the master form level, I’d suggest to create a CustomField extension to edit your Entity2 type and the just present that in your top level form. In layout you can still merge the fields to same level if you need to.
I also looked a bit how you could “merge” nested properties to the top level form. BeanFieldGroup (which AbstractForm uses behind the scenes), don’t have that great nested property support. That would need some enhancements for really handy usage, but I prototyped with some solution here: https://github.com/viritin/viritin/commit/56fe87019bc164030212b205842757bdafbc664d . No sure though if it is a good idea or not.
Check out the project from that feature branch (nestedpropertyabstractform) and issue mvn install -DskipTests. You chould get a development build to your local maven repository.
I should really look into that more some day and see if I’ll merge that to the master branch. It might be a nice addition.