Form with custom layout: how to place fields?

I’m trying to use the Form class, with a layout combinaison.

First, the form, as copy/pasted from the book:


// Create a form and use FormLayout as its layout.
final Form form = new Form();
// Set form caption and description texts
form.setCaption("Contact Information");
form.setDescription("Please specify name of the person and the city where the person lives in.");
// Create the custom bean.
PersonBean bean = new PersonBean();
// Create a bean item that is bound to the bean.
BeanItem item = new BeanItem(bean);
// Bind the bean item as the data source for the form.
form.setItemDataSource(item);

Then the layouts.


		VerticalLayout layout = new VerticalLayout();
		form.setLayout(layout);
		
		HorizontalLayout topHalf = new HorizontalLayout();
		layout.addComponent(topHalf);

		HorizontalLayout bottomHalf = new HorizontalLayout();
		layout.addComponent(bottomHalf);

In this example, I’ve 2 sub-layouts inside the layout of the form.
How to add a field in one of the sub-layout?

The form.setItemDataSource method calls the standard mechanism: form.addField.
addField adds the form to the layout and to a private map (form.fields).

I’d like to retreive my fields, to place them in the layouts myself, but how?

Should I do something like this?


Field nameField = ......."name"....;
bottomHalf.addComponent( nameField );

But how?

My current idea is to write a FieldFactory to collect the fields and put them in a map of mine just before calling the super method. Then, I could get the fields from my map to put them in my layout.
Is there a more natural way? I feel like I’m missing something.

Dammed!

I just noticed the Form.getField method…

So my code would be:

Field nameField = form.getField("name");
bottomHalf.addComponent( nameField );

Ok. The final solution looks like this:

Note that the setLayout method needs to be followed by a layout.removeAllComponent() call.

“this” is a subclass of Form.

		BeanItem item = new BeanItem(user);
		// Bind the bean item as the data source for the form.
		setItemDataSource(item);		
		setVisibleItemProperties(new String[]{"firstName", "lastName", "shortInfo"});
		setImmediate(true);

		
		VerticalLayout layout = new VerticalLayout();
		this.setLayout(layout);
		layout.removeAllComponents();  // because Form.setLayout moves all components from old to new layout, and we want to place the components ourselves (next action in the code below)
		
		HorizontalLayout topHalf = new HorizontalLayout();
		layout.addComponent(topHalf);
		
		// TODO: limit the input length.  -- John 2009-06-30
		firstNameField = getField("firstName");
		firstNameField.setDescription("In 'John Smith', the first name is 'John'.");
//        topHalf.addStyleName("orangeBackground");
		topHalf.addComponent(firstNameField);
//		
		// TODO: limit the input length.  -- John 2009-06-30
		lastNameField = getField("lastName");
		lastNameField.setCaption("last/family name");
		lastNameField.setDescription("Family name.");
		topHalf.addComponent(lastNameField);	
		
		
		
		HorizontalLayout bottomHalf = new HorizontalLayout();
		layout.addComponent(bottomHalf);
...

just want to add a little something to this thread:

It is possible to tell the form in which order the fields should be. You can use this if you are just retrieving your fields to reorder them in the layout:


Vector<String> order = new Vector<String>();
order.add("firstName");
order.add("lastName");
form.setItemDataSource(item, order);

if you just want parts of the form in two different layouts, then you can have two separate forms, one for both layout, and use the same item as data source for them.


BeanItem item = new BeanItem(pojo);
Vector<String> order = new Vector<String>();
order.add("firstName");
order.add("lastName");

form.setItemDataSource(item, order);

order = new Vector<String>();
order.add("city");
order.add("zip");
form2.setItemDataSource(item, order);

In this case, Jens, I guess that you have only one save button, which commits both forms.

form.commit();
form2.commit();

you, sir, are correct!