I am trying to implement a simple scenario binding a java bean to the form, where some bean properties should be read only (info data).
The issue is that the BeanFieldGroup.bind() does not accept labels. There are two possible workarounds for the issue:
1) Use of the read only TextField (.setReadOnly(true))
- Issue 1: bean validation fires even on the read only fields showing red mark (!)
- Issue 2: using BeanFieldGroup.setItemDataSource(T bean) resets the readOnly flag, which requires the code to set it back each time you update data of the form
2) Use of Label.setPropertyDataSource() binding it to a property of the BeanFieldGroup like BeanFieldGroup.getItemDataSource().getItemProperty(“propertyName”)
- Works only if you set the bean dataSource on the BeanFieldGroup before
- Binding gets lost if you perform BeanFieldGroup.setItemDataSource(T bean)
Is there any way to perform this task in an intuitive way?
I made myself a StaticTextField component , simply use CustomComponent , implement Field , display the value as text via a Label. ( in essence the StaticTextField does not ever try to convert the text to a value, it will only convert value ( via setValue ) to the text it wants to display in the label)
Many thanks for the suggestion. It would be for sure the third workaround which is even more “clean” than two others. Though, it would be great to hear from the Vaadin Team if this can be improved in the core because it seems to be a very common requirement.
Instead of implementing Field directly (lots of methods), you can extend CustomField, which is effectively a CustomComponent that already implements Field.
Such a read-only CustomField should be very short and easy to implement.
One thing from the initial post, which seems to require additional clarification, is:
“using BeanFieldGroup.setItemDataSource(T bean) resets the readOnly flag, which requires the code to set it back each time you update data of the form“
Petrus, I understand this behavior in case you first initialize a new FeildGroup and bind fields. But what if you just change the data in an existing field group using setItemDataSource(newBean)? I would not expect the field group to change anything in the UI representation. I expect it to update the data of the form keeping the form in the same state. Or is there any other method for this purpose?
To explain what I exactly mean I modified the book example:
// Have a bean
Person bean = new Person("Mung bean", 100);
// Form for editing the bean
BeanFieldGroup<Person> binder = new BeanFieldGroup<Person>(Person.class);
binder.setItemDataSource(bean);
//Test read only attribute
Field<?> name = binder.buildAndBind("Name", "name");
name.setReadOnly(true); //Read only flag set to true !!!
layout.addComponent(name);
layout.addComponent(binder.buildAndBind("Age", "age"));
// Buffer the form content
binder.setBuffered(true);
// Have a bean 2
Person bean2 = new Person("Mung bean 2", 100);
binder.setItemDataSource(bean2); //Read only flag reset to false (implicitly)!!!
Intension is here to set another bean to the same form (e.g. Master-Detail)… By the way, old vaadin 6 form worked differently: you could exchange beans.
Definately seems strange and is extremely painful to have to reset the readonly fields when you just want to update the data. I’m not sure the use case that behavior supports but at the very least it should be optional when changing the datasource.
I’m just in the process of evaluating, but this is kind of irritating. Doesn’t everyone need to bind read-only data to labels? Of course I could simply roll my own custom component, but the point of using a framework is to actually not have to do this for the most common use cases.
Please allow binding of labels via BeanFieldGroup.
Is there a reason why Vaadin itself doesn’t have such LabelField as part of the core? This is a rather common requirement to display a field.
EDIT TO ADD: The use of add-ons is much less appealing for such a basic feature as add-ons aren’t always maintained or supported the way a core feature is.
We actually like that our TextField, when handed one of our objects, uses the converter to change the model to presentation. But with a read-only TextField that is bound to a property with only a ‘get’ method an no corresponding ‘set’ method, it’s peculiar that there’s a converter exception trying to recreate my model object (no new object is needed as it’s read-only – nothing in the textfield changed – no is there even a way to update our bean with that new object. The converter is running to convert presentation back to the model when there’s simply no need to do so.
I can’t agree more that we should add and improve the parts in Vaadin that are actually used by our users. The LabelField is not the only thing we should add/change, there would be lots of things we should do regarding databinding in general and e.g. add a handlfull of compositions like confirm dialog. Our core team (me including in the past) has been too little involved with actual usage of the framework and thus much more keen to improve stuff like communication or component developement - something that is totally irrelevant for typical Vaadin users.
Once I switched over to do technical marketing, I just had to create Viritin with all the improvements to the core Vaadin as I wasn’t anymore able to affect the actual development of Vaadin as much as I would have liked to. Some small changes has gone in, but still lots of enhancements I’d love to see in core Vaadin as well. It is just one add-on (and contains no client side stuff) for the reasons you mentioned, so it should be pretty easy to add it and follow its developemnt.
I don’t know the converter stuff throughoutly, but I know it is pretty complex and does some kind of two-way conversion right at the start to detect some changes. It is probably hard to avoid as there is for example “field level buffering” available in Vaadin (
which you should never use ), but if you think the read-only mode should have special handling, feel free to add an enhancement request to dev.vaadin.com.
Added and issue, also did a little experiment and it seems it would be enough to simply implement HasValue for the Label component, but obviously I do not have the bigger picture
That’s it! On the DevDay in Zürich I tried to explain exactly this to the Vaadin team. Wasted effort. Example:
We are migrating our V7 application server monitoring tool to V8. Many screens are displaying live data delivered from sensors like CPU or memory usage. In V7 we could write a generic subscriber where any Property can bind sensor data as input. And Label with FontAwesome icons can present nice dashboards. Maybe TextFiled is semantic ok, but with FontAwesome the content looks terrible.
Now, in V8 we had to replace all labels with OurLabel implementation where OurLabel implements HasValue. 15 rows of code! IMO to make the migration 7 → 8 easy, any component, that implemented in V7 Property interface, should implement HasValue in V8.