How to validate fields in a Table

I am creating a table that has two columns. The first column is not editable. The second column is editable. The second column contains TextFields and ComboBoxs (I have set the table to be in edit mode and I created a TableFieldFactory for the second column). All of the fields in the second column are set to be required and validation visible. I am not seeing the red Asterisk as I should for any of the TextFields or the ComboBoxes but I am able to see the required message when I have the mouse over the TextFields. How do I get an individual fields errors to display correctly in a table?

Here is my createField method:

public Field createField(Container container, Object itemId, Object propertyId, Component uiContext) {
		Field field = null;
		if(propertyId != null && propertyId instanceof String) {
			Attribute attribute = getAttribute(itemId);
			if(propertyId.equals("attributeValue")) {
				List<AttributeValue> values = AttributeManager.getInstance().getAttributeValues(attribute.getAttribute());
				if(values.size() > 0) {
					ComboBox options = new ComboBox();
					options.setImmediate(true);
					options.setRequired(true);
					options.setRequiredError("This field is required!");
					options.setValidationVisible(true);
					for(AttributeValue value : values) {
						options.addItem(new AttributeValueNode(value));
					}
					field = options;
				} else {
					TextField textField = new TextField();
					textField.setImmediate(true);
					textField.setRequired(true);
					textField.setRequiredError("This field is required!");
					textField.setValidationVisible(true);
					field = textField;
				}
				field.setWidth("100%");
			}
		}
		return field;

This might go to the “you just have to know” file. In Vaadin, the caption and error markers are not rendered by components themselves. Instead, they are rendered by the containing layout (if any). In this case, you need to somehow wrap the fields in a layout and use that as a cell in the table. One solution might be to build a custom proxy that extends a layout, implements Field and delegates all field methods to the underlying field component.

I have created the proxy class that you suggested and now the error messages are displayed correctly.

Thank you

hi Douglas Thomsen
i had done follow direction of you ,but when build class proxy implement Field,
I know Field has AbstracField implement it directly
and when i implement it has error The inherited method AbstractComponent.focus() cannot hide the public abstract method in Component.Focusable
can you explain why
thank you

This is really an Eclipse issue: when adding “implements MyInterface” and then doing “implement missing methods”, Eclipse does not override protected methods with public ones even if the implemented interface requires such a public method.

Just add the method

public void focus() {
    super.focus();
}

Hi all
i have buld proxy class and write table field factory but table not edit
private HashMap<Object, HashSet> markedRows =
new HashMap<Object, HashSet>();
Table table=new Table()
table.addContainerProperty(“name”,ShowResultAndError.class,null);
table.addContainerProperty(“edit”,Button.class,null);
table.setTableFieldFactory(new TableFieldFactor(public Field createField(

			Container container, Object itemId, Object propertyId,
			Component uiContext) {

Field field=null;
if (markedRows.containsKey(itemId)) {
System.out.println(“co chua itemid”);
HashSet cells = markedRows.get(itemId);

}

if(propertyId.toString().equals("name")){
						System.out.println("create cell name");
				field = new TextField((String) propertyId);
						field.setData(propertyId);
						//field.setReadOnly(false);
						ShowResultAndError show=new ShowResultAndError(field);
						field=show;
						cells.add(field);
					
						
						
						markedRows.put(itemId, cells);
						
						
					}

return field;

)

my proxy class extend layout and implement Field it contain a TextField;
i try my best to find reason but now not yet
thanks for all direction

hey !

I’ve read the answers but I can not do. Anyone can give me a sample ?
Thank!

I’ve created a new class with a validateFields method that changes the styleName when the field isn’t valid:


public class Table2 extends Table {
    private ArrayList<Field> fields;

    public Table2() {
        fields = new ArrayList<Field>();
    }
    
    public void registerFieldToValidate(Field field) {
        fields.add(field);
    }
    
    public void validateFields() {
        for (Field field: fields) {
            try {
                field.validate();
                field.removeStyleName("err");
            }
            catch (Validator.InvalidValueException ex) {
                field.addStyleName("err");
            }
        }
    }
    
}

When you create the fields with the table field factory, call the registerFieldToValidate method to save a reference:


table.setTableFieldFactory(new TableFieldFactory() {

            @Override
            public Field createField(Container container, Object itemId, Object propertyId, Component uiContext) {
                TextField tf = new TextField();
                [b]
 table.registerFieldToValidate(tf);
[/b]
                  tf.setNullRepresentation("");
                  tf.setNullSettingAllowed(true);
                  tf.addValidator(new DoubleValidator("Incorrect number"));
                return tf;
            }
}

If you do this, don’t forget to unregister the fields when they go out of the view, especially if the table is very big with lazy loading in use.

Hello,

I am searching for a solution for the discussed problem, too.

I have a table with three columns and only the third column is supposed to be editable.

I have set the table to be editable (setEditable(true)) and set a TableFieldFactory. When I let the createField method return a normal TextField for the relevant column the column is editable, but when I let the createField method return my proxy class the column is
not
editable.

Proxy class:

package (...)

import java.util.Collection;

import com.vaadin.data.Property;
import com.vaadin.data.Validator;
import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.ui.Field;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.TextField;

public class Test extends HorizontalLayout implements Field {

    /**************************************************************************/

    private static final long serialVersionUID = 1L;

    /**************************************************************************/

    private TextField field;

    /**************************************************************************/

    public Test() {
        super();
    }

    public Test(final TextField field) {
        super();
        this.field = field;
    }

    /**************************************************************************/

    @Override
    public boolean isInvalidCommitted() {
        return this.field.isInvalidCommitted();
    }

    @Override
    public void setInvalidCommitted(final boolean isCommitted) {
        this.field.setInvalidCommitted(isCommitted);
    }

    @Override
    public void commit() throws SourceException, InvalidValueException {
        this.field.commit();
    }

    @Override
    public void discard() throws SourceException {
        this.field.discard();
    }

    @Override
    public boolean isWriteThrough() {
        return this.field.isWriteThrough();
    }

    @Override
    public void setWriteThrough(final boolean writeThrough) throws SourceException, InvalidValueException {
        this.field.setWriteThrough(writeThrough);
    }

    @Override
    public boolean isReadThrough() {
        return this.field.isReadThrough();
    }

    @Override
    public void setReadThrough(final boolean readThrough) throws SourceException {
        this.field.setReadThrough(readThrough);
    }

    @Override
    public boolean isModified() {
        return this.field.isModified();
    }

    @Override
    public void addValidator(final Validator validator) {
        this.field.addValidator(validator);
    }

    @Override
    public void removeValidator(final Validator validator) {
        this.field.removeValidator(validator);
    }

    @Override
    public Collection<Validator> getValidators() {
        return this.field.getValidators();
    }

    @Override
    public boolean isValid() {
        return this.field.isValid();
    }

    @Override
    public void validate() throws InvalidValueException {
        this.field.validate();
    }

    @Override
    public boolean isInvalidAllowed() {
        return this.field.isInvalidAllowed();
    }

    @Override
    public void setInvalidAllowed(final boolean invalidValueAllowed) throws UnsupportedOperationException {
        this.field.setInvalidAllowed(invalidValueAllowed);
    }

    @Override
    public Object getValue() {
        return this.field.getValue();
    }

    @Override
    public void setValue(final Object newValue) throws ReadOnlyException, ConversionException {
        this.field.setValue(newValue);
    }

    @Override
    public Class<?> getType() {
        return this.field.getType();
    }

    @Override
    public void addListener(final ValueChangeListener listener) {
        this.field.addListener(listener);
    }

    @Override
    public void removeListener(final ValueChangeListener listener) {
        this.field.removeListener(listener);
    }

    @Override
    public void valueChange(final com.vaadin.data.Property.ValueChangeEvent event) {
        this.field.valueChange(event);
    }

    @Override
    public void setPropertyDataSource(final Property newDataSource) {
        this.field.setPropertyDataSource(newDataSource);
    }

    @Override
    public Property getPropertyDataSource() {
        return this.field.getPropertyDataSource();
    }

    @Override
    public int getTabIndex() {
        return this.field.getTabIndex();
    }

    @Override
    public void setTabIndex(final int tabIndex) {
        this.field.setTabIndex(tabIndex);
    }

    @Override
    public boolean isRequired() {
        return this.field.isRequired();
    }

    @Override
    public void setRequired(final boolean required) {
        this.field.setRequired(required);
    }

    @Override
    public void setRequiredError(final String requiredMessage) {
        this.field.setRequiredError(requiredMessage);
    }

    @Override
    public String getRequiredError() {
        return this.field.getRequiredError();
    }

    @Override
    public void focus() {
        super.focus();
    }

    /**************************************************************************/

    public TextField getField() {
        return this.field;
    }

    public void setNullableTextField(final TextField field) {
        this.field = field;
    }

    /**************************************************************************/

}

Usage of the proxy class:

this.table.setEditable(true);
this.table.setTableFieldFactory(new TableFieldFactory() {

    private static final long serialVersionUID = 1L;

    @Override
    public Field createField(final Container container, final Object itemId, final Object propertyId,
            final Component uiContext) {
        final TextField textField = new TextField();
        textField.setImmediate(true);
        textField.addValidator(new RegexpValidator("(...)", "(...)"));        
        final Test test = new Test(textField);
        return "[columnId]
".equals(propertyId.toString()) ? test : null;
    }
});

What am I doing wrong?

Regards

Meik B.

Hello,

when I change the constructor of the proxy class from

public Test(final TextField field) {
    super();
    this.field = field;
}

to

public Test(final TextField field) {
    super();
    this.field = field;
    [b]
addComponent(field);
[/b]
}

the column is editable. :slight_smile:

Unfortunately there is no red exclamation mark when the validation fails. :frowning:

Regards

Meik B.

The
CustomField add-on
and the class FieldWrapper in it would let you avoid implementing and forwarding all methods of Field yourself - it takes care of it and you can still construct the layout yourself and override only what you need.

Hello Henri,

thanks for the hint. Maybe the add-on can simplify the solution, but does my approach include an obvious mistake or should it work this way, too?

Regards

Meik B.