Field Validation of multiple fields - Sample User Registration

Hello CUBA Team!

I’ve gone through the sample-user-registration example, and have recreated it successfully. However, in the sample, there is only one validation check. I need to do multiple.

I need the grid fields to do validation, for starters, but these seem to be ignored from the register-screen.xml file. For example:

                <label value="Email"/>
                <textField id="emailField" required="true">
                    <validators>
                        <notNull message="Email field must not be empty"/>
                    </validators>
                </textField>
            </row>

These are seemingly ignored, and the only validation is done is in the global module validation package.

The second part of this validation problem, is that I’ve created two separate validation checks in the global module validation package: One for checking the login exists and another for checking if the email exists. These both trigger correctly, but the problem is with how the RegisterScreen.java file establishes the validation, as it simply does a try/catch to validate, and immediately throws only one error if there is a failure. There isn’t a way to distinguish which errors are being triggered.

Please let me know the steps to share my project here so you can see how it’s set up and offer better advice.

Thank you very much in advance!
Adam

Thinking on it further, I’m wondering if, since I’m using Bean validation, if I need to use Bean validation for everything. If so, that’s okay. I can create those files. However, that would still leave me with the issue of needing to know how to draw multiple validation errors through the RegisterScreen controller where I’m calling my registration service. How should I properly go about setting this up?

Thanks!

Hello, Adam!

The validator in the field is ignored because screen does not trigger it. The common way to use field validators is validating fields in editor screens (StandardEditor). The editor triggers field validation when we try to commit an instance of entity.

For your case, as RegistrationScreen is not editor it needs to trigger validation manually. For instance:

<textField id="loginField">
    <validators>
        <notNull message="Login field is not filled"/>
        <size min="3" message="Login should contains at least 3 symbols"/>
    </validators>
</textField>

In the controller when we click on Ok button:

@Inject
private TextField<String> loginField;
@Inject
private Notifications notifications;

@Subscribe("okBtn")
public void onOkBtnClick(Button.ClickEvent event) {
    try {
        loginField.validate();
    } catch (ValidationException ex) {
        notifications.create(Notifications.NotificationType.TRAY)
                .withCaption(ex.getMessage())
                .show();
        return;
    }

   ...
}
1 Like

@Pinyazhin

Thank you very much for this explanation! It works very well.

To my second and main question on validation, my Bean validators check if the login exists, and if the email exists. However, using the sample-user-registration example, it only checks if the validation passes, and throws one message if it doesn’t pass. I need both messages: “Login exists” and “Email exists” to show. I’ve verified through testing that both validators work; if the login exists, I get the “Login Exists” message, and if the email exists, I still get the “Login Exists” message. I need both messages to show as appropriate. The code block in my RegisterScreen.java controller (following the example) is this:

try {
registrationService.registerUser(getFirstName(), getLastName(), getOrganization(), getPhoneNumber(), getEmail(), getLogin(), getPassword(), getConfirmPassword());

    notifications.create(Notifications.NotificationType.TRAY)
            .withCaption("Created user " + getLogin())
            .show();

    close(WINDOW_COMMIT_AND_CLOSE_ACTION);
} catch (MethodParametersValidationException e) {
    notifications.create(Notifications.NotificationType.TRAY)
            .withCaption(
                    messages.getMessage(
                            "com.company.userregtest2.validation",
                            "LoginExistsValidator.message"))
            .show();
}

}

I need a way to identify which validation has failed.

Edit: Sorry, I have a hard time getting the Blockquote to work correctly, so the formatting is bad.

As I understand you have separated validators for login and email? If you apply your validation on parameters in the registerUser() method, you can do the following:

@Subscribe("okBtn")
public void onOkBtnClick(Button.ClickEvent event) {
    try {
       ...
    } catch (MethodParametersValidationException e) {
        List<String> messages = e.getConstraintViolations().stream()
                .map(ConstraintViolation::getMessage)
                .collect(Collectors.toList());
        String message = Joiner.on("\n").join(messages);
        notifications.create(Notifications.NotificationType.TRAY)
                .withCaption(message)
                .show();
    }
}

We just collect messages from constraint violations and show them in the notification. These messages can be defined in your annotations, see @CheckUserExists.

1 Like

@Pinyazhin

Thank you so much! You have provided exactly what I need.