Can Form handles pojo within a pojo? For example a pojo Person has an attribute Address which is another pojo.
Sure it can, but you’ll have to done some work to get it the way you want. The form cannot know how you want to display the Address reference, do you want it to be a select component where you select one available addresses or do you want the address to render as a form itself?
Either way, you’ll have to create a FormFieldFactory. In the FormFieldFactory, you can specify which types of Fields are created for each of the properties. In your case, you’ll most likely want to render another form for the address field. Forms implement the Field interface, so you can have the FormFieldFactory return a Form, thus creating nested forms.
Check out the
Book of Vaadin
for more information about Forms and FormFieldFactories.
Takes out his crystal ball I think your next question will be how to have in a form some fields rendered horizontally side-by-side each other, for example the “city” and “zip” fields in your address pojo. The answer to this question can be found by searching the forums.
That’s an awesome tip. I have built a Form using an overridden DefaultFieldFactory, but hadn’t considered putting a Form inside a Form, so presumably the property “address” would return a Form that would then list the properties to be used in that sub-Form.
How would you generally tie the two forms together since often enough in a scenario like that you’d still only want the one set of buttons to Save/Cancel, etc. Do you just not defined any buttons on the sub-Form and keep the footer unspecified?
Then a commit() or discard() on the main form would automatically do the same on the sub-Form? It seems reasonable, very cool, but hadn’t thought of it as an option.
Such a sub-Form would also make a good fit for the Drawer widget in contrib, or some sort of popup if the sub-Form was pretty busy.
You’ll only need on set of buttons, as as you suspected, a commit() or discard() will cascade to the inline form.
nice one! didn’t know this was possible. I’ve got a similar problem: pojo containing an attribute that is a set of pojos (i.e. document->references (Set) ). Any ideas on how to implement a solution for that?
Maybe return a table component in the custom fieldfactory?
I have a quite similar problem like hendri.
I have a class with an attribute that is a list of another class. (I will add some code snippets)
public class Person
{
private String name;
private Address address;
private List<Pet> petList = new LinkedList<Pet>();
}
pubic class Address
{
private String city;
private String street;
}
public class Pet
{
private String name;
private String kind;
}
Now i created a wizard. I set the a person bean item as item data source and change the displayed item properties for each wizard page. I used a custom form field factory.
On the first page i can set the name ->works fine
On the second page i set the address (the field is a new form with a address bean item) → this works fine too
But then on the third page i got troubles. I want to show a combo box for the animal kinds. And a text field for the name
here the code
form:
setVisibleItemProperties(Arrays.asList(String [] {"petList"}));
form field factory:
if ("petList".equals(propertyId))
{
List<Pet> petList= ((BeanItem<Person>) item).getBean().getPetList();
Form petParentForm = new Form();
petParentForm .setWriteThrough(false);
petParentForm .setInvalidCommitted(false);
petParentForm .setImmediate(true);
petParentForm .setFormFieldFactory(null);
Form form = new Form();
form.setWriteThrough(false);
form.setInvalidCommitted(false);
form.setImmediate(true);
form.setFormFieldFactory(this);
if (petList.size() == 0)
{
Pet pet= new Pet();
petList.add(pet);
form.setItemDataSource(new BeanItem<Pet>(pet), Arrays.asList(new String[] { "name", "kind" }));
petParentForm .getLayout().addComponent(form);
}
}
The form for the pet is displayed but when i push the commit button the values from the form aren’t committed.
From my point of view i need the 3 forms because i want to add another pet forms when a user set a pet (so he is not restricted to one pet).
Did someone see there the problem is? I can add other code snippets if someone needs? Is the problem the petParentForm? Is it necessary to set a item data source for this form?
I’m glad for any advise
Greetings
Christian
PS.
For displaying an existing person i use the form and change the form to read only. What should i do with the inline forms? Is it possible to change all components to read only?
What do you actually do when the list isn’t empty?
Also what is this petparentform? it is not very clear in the code you posted… Why do you create this form in the formfield factory? Where do you add it?
How do you commit the main form? Are you sure the beans are not updated?
Anyway, I had the same kind of problem and applied a different solution.
I have some contacts who have multiple bank accounts. What I did is display a table of the bank accounts in another tab, and add controls for that specific table. So I can add,remove or delete accounts easily. It has its own commit and discard controls. Though I could link this to the main form commit.
Hi Fluffy,
I removed the parts for the case the list isn’t empty.
And as i wrote this is the part for the “create-a-person-wizard”. So the list is definitely empty.
The petParentForm is the field i returned for the property petList and is added to the wizard form. I want to make the form for the pets dynamic. So I need a container form there i can add other input forms for pets. Let me describe a little example.
Then the user comes to this page he will see 1 pet kind combo box which is empty and 1 text input for the name.
If he select a pet kind another combo box and text field is added, so he can add another pet and so on. This code i stripped because it has nothing to do with my problem.
The main form is committed by a regular commit. (wizardForm.commit() And I’m really sure that the beans aren’t updated, but i will check this again.
Thanks for the idea with the separate table. I will check if this works for me.
If it is necessary i can post the whole code…
So you actually return the petparentform in the createfield function?
I think the problem is that the subform petparentform has no subform of pets, but you just add the subsubforms in the layout, so the petparentform datasource doesnt know it has subforms, so it doesnt commit them.
edit : maybe you could override the commit() function of the petparentform to iterate through the subforms and commit() each one?
Correct
Do you know a way to add the form as a subform so the commit is done automatically?
If i add the list as item data source i got the properties empty, first, last.
But i need a something there i can add properties dynamically because at the beginning i don’t know how many pets a person has. Or did i miss something?
I don’t have enough experience to give you an enlightened reply unfortunately.
Normally you should handle that in the overriden createfield method but I don’t see how you can do that dynamically in this specific case.
Maybe a solution would be to create a custom pet table which includes logic to add new bean when the last field is selected, and return the table in the createfield method? normally the commit function should call the commit on the table as well.
edit : tried myself, and the table thing works. Commit is called on every property including the table.
If you want to control the new pets in a table, maybe you can have a generated column with a button which creates a new bean instance and inserts it in the table?
_table.getContainerDataSource().addItem(this._type.newInstance());