Error message of UserError

Hello,
how setComponentError(xx) should be used to print an error message on the screen?
Currently I try to use a following code:


TextField aTextField = new TextField();
aTextField.setRequired(true);
...
try{                    
aTextField.validate();
} catch (Validator.InvalidValueException e){
 aTextField.setComponentError(new UserError("Name is required"));
}
 

If the aTextField is empty, the field is turned red and an exclamation mark is shown, but the text “Name is required” is not printed anywhere. Do I have to set the target for error message manually or have I missed something else?

I’m using Toolkit version 5.2.4 (beta).

Thanks,
Juha

There isn’t currently any automatic feedback if a required field is empty. The required property is mainly intended to be used in Form component, which displays the component error of contained fields in the bottom of the form. It displays an error if a required field is empty, but currently that error message is empty and shows just an exclamation mark “!”.

I’m not quite sure what the current plans for the required fields are. I don’t think catching validation errors of the fields is the proper way to go, especially for Forms. My suggestion is to add
setRequiredMessage()
(or -Error?) method to AbstractField (and to Field interface), so that you could say:


form.getField("name").setRequired(true);
form.getField("name").setRequiredMessage("Name is missing");

or maybe also have it possible to give the message in
setRequired()
:


form.getField("name").setRequired(true, "Name is missing");

A Form would then automatically show the error as shown:

Or is this too much an ad hoc solution?

There isn’t currently any color or other feedback for empty required field in the required field itself.

Current version of toolkit validates component again in paint-phase. If you happen to set compomenterrors manually, they are cleared and reset in paint.

To use automatic validation use:

field.addValidatator(new EmptyFieldValidator("Name is Required")) ;

To use manual validation:

field.addValidatator(new EmptyFieldValidator("Name is Required")) ;
field.setValidationVisible(false);

and validate it when you like (view-transition, button click, value change,…):

for (AbstractField field : allFieldsInForm) {
  try{                    
    field.validate();
    field.setComponentError(null);
  } catch (InvalidValueException e){
     field.setComponentError(new UserError(e.getMessage()));
  }
}

Now besides described validation, there is one extra case and that is REQUIRED. If field is set required its componenterror is not shown when value is “” or null.

What required field should do is that it should validate first with validators and then check “” or null situation. If it worked this way, you still could do:
field.addValidatator(new EmptyFieldValidator(“Name is Required”)) ;
and field.validate()s thrown Exception would have message “Name is Required”

Hi, thanks for the comments. I’ll try to use the Form-component in a more correct way.

Your suggestions about api changes sounds good. In addition, I’d like to use the setRequiredMessage(“”) without a Form and get the error message printed in next of the missing field. Maybe after I’ve learned to use the Form, this will be irrelevant :?

In fact I would like to disable a submit button until all the required fields are filled and are valid (my other thread as Anonymous http://forum.itmill.com/posts/list/435.page)

By the way where can I find documentation about validating form elements or using setComponentError()? At least the Reference Manual is not very informative: http://www.itmill.fi/documentation/itmill-toolkit-5-reference-manual/ch04s13.html#section.ui.form.validation and http://www.itmill.fi/documentation/itmill-toolkit-5-reference-manual/ch03s06.html

Thanks,
Juha

Hi,

The UserError is shown in the tootip, if you want it elsewhere you can for instance add a Label manually (we can’t really add the error-text elsewhere automatically, since that might break the UI).
So, what you tried should basically work:


        tf = new TextField("Name");
        main.addComponent(tf);
        tf.setRequired(true);

        main.addComponent(new Button("Validate", new Button.ClickListener() {

            public void buttonClick(ClickEvent event) {
                try {
                    tf.validate();
                    tf.setComponentError(null);
                } catch (Exception e) {
                    tf.setComponentError(new UserError("Name is required"));
                }

            }

        }));

Result after clicking the button, and the hovering the textfield:

There has been some changes to how the validation works, and how it’s displayed, hence the confusion; we’re trying improve the usefullness of this feature - feedback is welcome :slight_smile:

Some final thoughts on usability: if you have several fields that are validated when the user presses a button, you might want to add a Label close to the button (as in Markos example above), and indicate that something is wrong (e.g “Some required values are missing, please check the form”), and use ComponentError to ‘mark’ the invalid fields (you can also show a summary of the errors in the Label, e.g “Please enter your name and shoesize”). Adding a ComponentError to Button is seldom (read: never) useful - the button does not fail (the user can only press it in one way), something else causes it to fail.

Anyway, I’ll check the current state of the Validation/Error changes; it seems it’s not quite finished…

Best Regards,
Marc

What really annoys me is that you have to KNOW the field when you validate to add it correct errormessage.

Lets say you have 10 TextFields: Without “required”, you can do this:

for (AbstractField field : formFields) {
            try {
                field.validate();
                field.setComponentError(null);
            } catch (InvalidValueException e) {
                field.setComponentError(new UserError(e.getMessage()));
            }
        }

Since e.getMessage() contains right validation error for that message. If field is required, e.getMessage() returns “”.

Made a simple validation example: (Try setting name required and see how it affects validation.)


package com.itmill.toolkit.tests.tickets;

import java.util.ArrayList;

public class SimpleValidationTest extends com.itmill.toolkit.Application implements
        ValueChangeListener {

    private ArrayList<AbstractField> formFields;
    private Button myButton;

    public void init() {

        final Window main = new Window(getClass().getName().substring(
                getClass().getName().lastIndexOf(".") + 1));
        formFields = new ArrayList<AbstractField>();

        setMainWindow(main);

        OrderedLayout orderedLayout = new OrderedLayout();
        TextField name = new TextField("Name");
        name.addValidator(new StringLengthValidator("Name required", 1, Integer.MAX_VALUE, false));
        name.setValue("");
        name.setImmediate(true);
        name.setValidationVisible(false);
       // name.setRequired(true);
        name.addListener(this);
        orderedLayout.addComponent(name);
        formFields.add(name);

        TextField email = new TextField("Email");
        email.addValidator(new SimpleEmailValidator("Invalid email", true));
        email.setValue("");
        email.setImmediate(true);
        email.setValidationVisible(false);
        email.addListener(this);
        orderedLayout.addComponent(email);
        formFields.add(email);

        myButton = new Button("proceed");
        myButton.setEnabled(false);
        orderedLayout.addComponent(myButton);
        main.addComponent(orderedLayout);
    }

    public void valueChange(ValueChangeEvent event) {
        if (isFormValid()) {
            myButton.setEnabled(true);
        } else {
            myButton.setEnabled(false);
        }
    }

    private boolean isFormValid() {
        boolean isValid = true;
        for (AbstractField field : formFields) {
            try {
                field.validate();
                field.setComponentError(null);
            } catch (InvalidValueException e) {
                field.setComponentError(new UserError(e.getMessage()));
                isValid = false;
            }
        }
        return isValid;
    }

    public class SimpleEmailValidator implements Validator {
        String errorMessage = "";
        boolean allowEmpty = true;

        public SimpleEmailValidator(String string, boolean b) {
            errorMessage = string;
            allowEmpty = b;
        }

        public boolean isValid(Object value) {
            if (value == null || value.toString().equals("")) {
                return allowEmpty;
            }
            if (value.toString().contains("@")) {
                return true;
            }
            return false;
        }

        public void validate(Object value) throws InvalidValueException {
            if (!isValid(value))
                throw new InvalidValueException(errorMessage);
        }

    }
}

Hello,
what is a correct usage of setComponentError and TwinColSelect?

When I us twinCol.setComponentError(new UserError(null)) the exclamation mark is turned on. If this is a feature, how can I remove an error message from TwinColSelect after it is valid?

I’m using 5.2.4 (beta).

Thanks,
JuHa

Use twinCol.setComponentError(null);

Thanks for a very quick response
and sorry for being too trigger happy :oops:

I am trying to employ an “EmptyFieldValidator” as I don’t want the default behavior associated with setRequired(true) (the red asterisk and associated field level messages). I discovered however that my Validator isn’t being called due to the following code in AbstractField

    if (isEmpty()) {
        if (isRequired()) {
            throw new Validator.EmptyValueException(requiredError);
        } else {
            return;
        }
    }

Can you suggest an approach for me when validating fields for required that would allow me to not show the visual indicator of an asterisk? Is there some css or property that I can modify to control the appearance of the red asterisk?

you can overrides general behavior of your UI error catching (including fields validators)
In your class which extends UI, add the following code (inside C-tor)

    // Configure the error handler for the UI
    setErrorHandler
    (
        new DefaultErrorHandler()
        {
            @Override
            public void error(com.vaadin.server.ErrorEvent event)
            {
                // Find the final cause
                String cause = "<b>Operation error:</b><br/>";
                for( Throwable t = event.getThrowable(); t != null; t = t.getCause() )
                {
                    if (t.getCause() == null) // We're at final cause
                        cause += t.getClass().getName() + "<br/>";
                }

				// ==> you can use Vaadin Notification to display your errors
				// (I have a special class for that but you may use Notification.show(...)
                JetNotifs.DoVaadinErrorNotif(cause);
                
				// Do the default error handling (optional)
				// Commenting out the doDefault will prevent the red '!' mark on fields with validation failure
                // doDefault(event);
            }
        }
    );