Luke
Luke

Reputation: 768

Grouping form errors in Play! Framework

Is there an easy way to group form errors at the top of the form, rather than above each field?

Here is my Scala template:

@(registrationForm: Form[User])

@implicitField = @{ FieldConstructor(views.html.helper.twitterBootstrap2.twitterBootstrap2FieldConstructor.f) }

@import helper._

@helper.form(action = routes.Registration.index) {

    <fieldset>

        @if(registrationForm.hasGlobalErrors) { 
            <div class="alert alert-error">
            <a class="close" data-dismiss="alert">×</a>
                @registrationForm.globalError.message
            </div>
        }

        <legend>Register</legend>

        @inputText(
            registrationForm("firstName"),
            '_label -> "First Name",
            '_showConstraints -> false,
            '_showErrors -> true,
            '_error -> registrationForm.error("firstName")
        )

        @inputText(
            registrationForm("lastName"),
            '_label -> "Last Name",
            '_showConstraints -> false,
            '_showErrors -> true,
            '_error -> registrationForm.error("lastName")
        )

        @inputText(
            registrationForm("emailAddress"),
            '_label -> "Email Address",
            '_showConstraints -> false,
            '_showErrors -> true,
            '_error -> registrationForm.error("emailAddress")
        )

        @inputPassword(
            registrationForm("password"),
            '_label -> "Password",
            '_showConstraints -> false,
            '_showErrors -> true,
            '_error -> registrationForm.error("password")
        )

        @inputPassword(
            registrationForm("password"),
            '_label -> "Confirm Password",
            '_showConstraints -> false,
            '_showErrors -> true,
            '_error -> registrationForm.error("password")
        )

    </fieldset>

    <button type="submit" class="btn">Register</button>

}

I have a custom validation that I'm doing to check for unique email address and based on that validation, I add an error to the global errors. I'd like to have any additional errors (that are thrown as a result of validation of other fields) grouped together with this error at the top of the form. Any suggestions?

Upvotes: 2

Views: 3377

Answers (2)

Jeff LaJoie
Jeff LaJoie

Reputation: 1725

In your @if(registrationForm.hasGlobalErrors){ you could always try calling registrationForm.globalErrors to get the List of all errors, traverse it, and output the message for each?

example:

@if(registrationForm.hasGlobalErrors){
    <div class="alert alert-error">
         @for(validationError <- registrationForm.globalErrors){
              <a class="close" data-dismiss="alert">×</a>
              @validationError.message
         }
    </div>
}

EDIT: At the request from the comments below I'm updating my answer to include an alternative method for grouping custom validation messages, which may not be the "best" solution but should accomplish just that.

In your controller:

if(filledForm.hasErrors()){

       for(String key : filledForm.errors().keySet()){
           List<ValidationError> currentError = filledForm.errors().get(key);
           for(ValidationError error : currentError){
               flash(key, error.message());
           }
       }
}

Or you could use an iterator, whichever you prefer.

And then in your view something along the lines of:

@if(flash.size() > 0){
    <div class="alert-alert error">
        @for((key, value) <- flash){
            <strong>Error : </strong> @value<br />
        }
    </div>
}

Like I mentioned, not the most elegant solution, but it should get a big list of your errors at the top of your page.

Upvotes: 5

Miguel
Miguel

Reputation: 53

I have had also problems adding custom global errors to globalErrors and displaying them on the view. My solution is use the errors object and add these global error under "global" key. Then in the view I display all "global" errors at the top.

My view:

@for(error <- form("global").errors) {
       <p>@error.message</p>
}

My controller:

ValidationError error = new ValidationError("global", "User is not authorized.");
List<ValidationError> errors = new ArrayList<ValidationError>();
errors.add(error);
loginForm.errors().put("global", errors);
return badRequest(login.render(loginForm));

Upvotes: 1

Related Questions