Loading...
Important Notice - Forums is archived

To simplify things and help our users to be more productive, we have archived the current forum and focus our efforts on helping developers on Stack Overflow. You can post new questions on Stack Overflow or join our Discord channel.

Product icon
TUTORIAL

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.

How to attach more than one bean in a form

Tam Nguyen Minh
1 decade ago Jan 09, 2012 3:29am
Javier Serrano
1 decade ago Jan 09, 2012 12:59pm
Tam Nguyen Minh
1 decade ago Jan 10, 2012 8:17am
Henri Sara
1 decade ago Jan 10, 2012 8:40am

Tam Nguyen Minh: I already have two beans Subject and Details

public class Subject extends GeneratedKeyBaseEntity
{
    @Column(name = "name", nullable = false)
    private String name;
...    
    @OneToOne(fetch = FetchType.LAZY, mappedBy = "subject")
    private Details detail;
...
public class Details extends GeneratedKeyBaseEntity
{
...
    @Column(name = "content", nullable = false)
    private String content;
....

But I don't know how to put them in same form

If you are using explicitly created BeanItems, the easiest solution is probably to use nested properties. Otherwise, check what the container you are using might provide - if I remember correctly, e.g. BeanContainer and JPAContainer support telling the container to automatically add specified nested properties to their items.

The code could look something like

myBeanItem.addItemProperty("content", new NestedMethodProperty(myBeanItem.getBean(), "detail.content"))

Vaadin 7 will also make adding nested properties directly to BeanItems a little easier with a helper method for the above.

EDIT: As you seem to be using JPA, make sure lazy loading does not cause problems - if necessary, force the loading of lazy fields. Depending on your use of the item, the JPA library used etc. this may or may not be a problem for you.

Last updated on Jan, 10th 2012
Tam Nguyen Minh
1 decade ago Jan 11, 2012 3:32am
Javier Serrano
1 decade ago Jan 11, 2012 9:32am

Hi Tam,

First of all, you don't have to thank nothing it's really a pleasure for me help other developers, also when my answer doesn't fit the needs of them :unsure:

And now, after read your post and review the code you post

Tam Nguyen Minh:

BeanItemContainer<Details> detailsBean = new BeanItemContainer<Details>(Details.class);
List<Details> detailsList = //code to get list of detail objects
detailsBean.addAll(detailsList );
Table table = new Table();
table.setContainerDataSource(detailsBean )

I think that the use of a table for your data structure is not bad, you can set editable mode on table and add a TableFieldFactory that shows the "content" property in bean as TextField (or TextArea as you prefer) and then save the changes you made on bean in table to your database, adding a Listener

There is a good example of how to implement this in the Book of Vaadin, and also here in the Book Examples Application you can view http://demo.vaadin.com/book-examples/book/#component.table.editable.

The code snippet could be similar to this one:

BeanItemContainer<Details> detailsBean = new BeanItemContainer<Details>(Details.class);
List<Details> detailsList = //code to get list of detail objects
detailsBean.addAll(detailsList );
Table table = new Table();
table.setContainerDataSource(detailsBean )
table.setTableFieldFactory(new DefaultFieldFactory() {
    @Override
    public Field createField(Container container, Object itemId, Object propertyId, Component uiContext) {
        // Create a TextField if the propertyId is content property of your Detail class
        if ("content".equals(propertyId)) {
            return new TextField();
        }
        // Otherwise use the default field factory 
        return super.createField(container, itemId, propertyId,uiContext);
    }
});
// Add ValueChangeListener to listen changes on table data
table.addListener(new Property.ValueChangeListener() {
    @Override
    public void valueChange(ValueChangeEvent event) {
          // Implement the logic to save your entity here
});
// Make table editable
table.setEditable(true)

Hope this helps, but if Henri has another idea, problably should be better than mine :)

Cheers,

Javi

Last updated on Jan, 11th 2012
Henri Sara
1 decade ago Jan 11, 2012 9:51am

Javier Serrano: I think that the use of a table for your data structure is not bad, you can set editable mode on table and add a TableFieldFactory that shows the "content" property in bean as TextField (or TextArea as you prefer) and then save the changes you made on bean in table to your database, adding a Listener

I agree that an editable Table is often a good approach in such situations, and can also be supplemented with controls to add/remove rows etc. if necessary. Note, though, that the value of a Table (also when on a Form) is the selected row id (or a Set of them for a multiselectable table), which can cause some complications if you put the table directly as a field in the form. You can get around this e.g. by wrapping the table in a CustomField and returning for instance a list of your beans or some other suitable representation - or by preventing the form from saving the value of that field and just using it for in-place editing.

Another option - in case you want the content fields of the sub-objects directly on the form - would be to add related properties by hand (e.g. looping over a list of sub-beans) to your BeanItem and then displaying the item on the Form. You could use MethodProperty, NestedMethodProperty or your own custom Property implementations (inheriting AbstractProperty) for this, and have a little helper class or a subclass of BeanItem to automate all this.

Tam Nguyen Minh
1 decade ago Jan 12, 2012 2:55am