Wednesday, December 11, 2013

Vaadin TextFields in a Table empty/null value not propagated for required field

Setup

Problem

When you create a table in Vaadin with a .setTableFieldFactory(), and you have a Field which is set to .setRequired(true), and a user puts in an empty value for that field after first putting in a non-empty value, the field won't be set to that empty value when iterating through the table to read the current values.

Solution

Make sure you invoke .setInvalidCommitted(true) on that field to have the empty value also be passed through; i.e "committed" even though validation fails.

For example:

urlTable.setTableFieldFactory(new DefaultFieldFactory() {

    @Override
    public Field createField(final Container container, final Object itemId, final Object 
                    propertyId, Component uiContext) {

    if (URL_PROPERTY_ID.equals(propertyId)) {
        
        final TextField urlText = new TextField();
        urlText.setRequired(true);

        // Add the below line to have also the empty string be
        // passed on!!
        // See: https://vaadin.com/forum#!/thread/1129126
        urlText.setInvalidCommitted(true);
        urlText.setImmediate(true);
        urlText.setNullRepresentation("");
        urlText.setInputPrompt("Enter a URL");
        return field;

}

Note the bold line.

And for completeness here an example of the iterating over the table to get the current entered values:

List result = new ArrayList();
int sequence = 1;
for (Iterator iterator = urlTable.getItemIds().iterator(); iterator.hasNext();) {

    // Get the current item identifier
    String itemId = (String) iterator.next();

    // Now get the actual item from the table.
    Item item = linksTable.getItem(itemId);
    @SuppressWarnings("unchecked")
    Property urlProperty = item.getItemProperty(URL_PROPERTY_ID);
    String url = urlProperty.getValue();

    // Fill the object
    UrlInfo urlInfo = new UrlInfo();
    urlInfo.setUrl(url);
    // ... set other stuff
    result.add(urlInfo);
    sequence++;
}

return result;

Related resources

The forum thread that put me on the right track can be found here.
Long thread related to required vs validation problems can be found here.
@NotNull bean validator annotation combined with setRequired() also has some issues.