BeanFieldGroup and Label (or read only texts)

Hi All,

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?

Many thanks
Dimitri

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.

Henri,

many thanks for this valuable hint. For colleagues who face the same issue, here is a chapter in the book describing the idea:

https://vaadin.com/book/vaadin7/-/page/components.customfield.html

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“

or is this an intention?

The FieldGroup set the fields readOnly and buffered Status when it binds the field, (ie it is intentional).


    protected void configureField(Field<?> field) {
        field.setBuffered(isBuffered());

        field.setEnabled(isEnabled());

        if (field.getPropertyDataSource().isReadOnly()) {
            field.setReadOnly(true);
        } else {
            field.setReadOnly(isReadOnly());
        }
    }

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.

Hi Reto,

Add Viritin add-on to your project. You’ll want to do it in each and every project for other reasons as well :wink:

It contains LabelField component, built exactly for this use case:
https://github.com/viritin/viritin/blob/master/src/main/java/org/vaadin/viritin/fields/LabelField.java

cheers,
matti

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.

Hi,

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.

cheers,
matti

Has this been ‘resolved’ for vaadin8?

Because it seems binder only accepts HasValue objects, which Label is not (which is strange, because actually Label Has(a)Value :P).

I asked this from the core team and the answer is sadly no.

Would you file an enhancement issue about this
to github
?

cheers,
matti


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 :slight_smile:

It might be that you have big enough picture and that the core team just haven’t had enought time to look the big picture :wink:

Thanks for the issue!

cheers,
matti

As far as I know, binding a read-only TextField should work fine in Vaadin 8 and is a semantically correct solution.

Yep, tried it, works and semantically is the same, bo what I care about is the looks :wink: Sure I could style it to ‘match’, but that’s not the point.

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.

Robert