Howto validate a generated form field?

Hi

I’m new to Vaadin and I thought I should give it a try after seing a presentation at JFocus yesterday. The manual seem very comprehensive but there seem to be one vital little piece of information missing.

I’m just playing around with a simple form with name, address, zip and country fields. I’m using the method of letting Vaadin generate the form from my bean class.

My problem is that I can’t figure out how to validate the generated form fields?

I’ve tried using a form field factory but the createField method is never called which means that it is never used by the form to create the text fields.

I have pasted my code below, both the Address.java class and the TestApplication.java class.


public class TestApplication extends Application {
	
	@Override
	public void init() {
		Window mainWindow = new Window("Address");
		
		// Create and initialize the address form.
		Form form = new Form();
		form.setCaption("Enter address");
		form.setDescription("Enter your address");
		form.setImmediate(true);
		form.setItemDataSource(new BeanItem<Address>(new Address()));
		
		// Use a form field factory to be able to change the null
		// representation and set validators etc.
		//
		// This code never gets called though!! Why?
		//
		form.setFormFieldFactory(new FormFieldFactory() {
			@Override
			public Field createField(Item item, Object propertyId, Component uiContext) {
				TextField text = new TextField();
				text.setNullRepresentation("");
				text.addValidator(new RegexpValidator("", "String must be at least 1 character long"));
				text.setImmediate(true);
				text.setRequired(true);
				return text; 
			}
		});
		
		// Create the commit button that calls the commit method
		// on the form when clicked.
		Button commitButton = new Button("Commit", form, "commit");
		
		// Add the form and the commit button to the main window.
		mainWindow.addComponent(form);
		mainWindow.addComponent(commitButton);
		
		setMainWindow(mainWindow);
	}
}

public class Address implements Serializable {
	private static final long serialVersionUID = -6721566604911217965L;
	private String name;
	private String address;
	private String zip;
	private String city;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public String getZip() {
		return zip;
	}
	public void setZip(String zip) {
		this.zip = zip;
	}
	public String getCity() {
		return city;
	}
	public void setCity(String city) {
		this.city = city;
	}
	
}

I hope you can help me with this.

By the way, I attached a file displaying what the form looks like in the browser.

Regards,
Mattias

11595.png

Adding the lines in bold actually makes the form require non null values in the name and address fields (see attached screenshot).


		.....
		form.setItemDataSource(new BeanItem<Address>(new Address()));
		
		[b]
form.getField("name").setRequired(true);
		form.getField("name").setRequiredError("Name is missing");
		form.getField("address").setRequired(true); // No error message
[/b]
		
		// Use a form field factory to be able to change the null
		// .....

I still have the problem with not being able to set the null representation and other types of validators on my text fields in the form though. So any help with that would be greatly apprechiated :slight_smile:
11596.png

Hej och välkommen, Mattias! :slight_smile:

The problem is that you set the FieldFactory after having already set the item data source. This means that the fields are generated with the default field factory when you set the item data source. In order to have your field factory used, you need to set the field factory before setting the item.

This should take care of all the problems, as you should now be able to set the validation in the FieldFactory as well.

HTH,
/Jonatan

Hej, och tack för välkomnandet och för hjälpen!

Jag antar att vi håller konversationen på engelska så andra, icke svenska-talande, kan få nytta av den här tråden också :slight_smile:

Thanks for your suggestion. I moved setItemDataSource after the call to setFormFieldFactory and now my custom FormFieldFactory gets called.

But now the text fields doesn’t have captions. Am I supposed to use the propertyId for caption like this?


form.setFormFieldFactory(new FormFieldFactory() {
	@Override
	public Field createField(Item item, Object propertyId, Component uiContext) {
		[b]
TextField text = new TextField((String)propertyId);
[/b]
		text.setNullRepresentation("");
		text.addValidator(new StringLengthValidator(
			"must be at least 1 and at most 20 characters", 1, 20, false));
		text.setRequired(true);
		return text; 
	}
});

Also, this leaves me with lower case captions, e.g. address, name etc instead of Address, Name etc. Am I supposed to fix that also in the FormFieldFactory?


String caption = (String)propertyId;
caption = caption.substring(0,1).toUpperCase() + caption.substring(1);
TextField text = new TextField(caption);

All I really want is a form with validated fields with captions that are capitalized and empty null representations. Do I have to go through all this hassle or is there an easier way?

Regards,
Mattias

If you want to use the property ID for the caption, there’s a static method createCaptionByPropertyId() in DefaultFieldFactory, which makes nice captions from property IDs, such as “cityName” → “City Name”.

The perhaps more typical use for the property ID is to differentiate between the different fields, so you can construct them differently and you can give a proper field name then as well. For example, “if (propertyId.equals(“cityName”)) {field = new TextField(“City Name”); … } else if () …”.