Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to print validation error outside of field constructor in Play framework 2

How can I show a validation error for a form field outside of a field constructor in Play framework 2? Here is what I tried:

@eventForm.("name").error.message

And I get this error:

value message is not a member of Option[play.api.data.FormError]

I'm confused because in the api docs it says message is a member of FormError. Also this works fine for global errors:

@eventForm.globalError.message
like image 321
TomahawkPhant Avatar asked Dec 22 '12 17:12

TomahawkPhant


2 Answers

You can get a better grasp of it checking Form's sourcecode here

Form defines an apply method:

 def apply(key: String): Field = Field(
    this,
    key,
    constraints.get(key).getOrElse(Nil),
    formats.get(key),
    errors.collect { case e if e.key == key => e },
    data.get(key))

That, as said in the doc, returns any field, even if it doesn't exist. And a Field has an errors member which returns a Seq[FormError]:

So, you could do something like that (for the Seq[FormError]):

eventForm("name").errors.foreach { error =>
  <div>@error.message</div>
}

Or (for the Option[FormError])

eventForm("name").error.map { error =>
  <div>@error.message</div>
}

Or, you could use Form errors:

  def errors(key: String): Seq[FormError] = errors.filter(_.key == key)

And get all errors of a given key. Like this (for the Seq[FormError]):

eventForm.errors("name").foreach { error =>
      <div>@error.message</div>
}

Or (for the Option[FormError])

eventForm.error("name").map { error =>
          <div>@error.message</div>
}

If you want more details, check the source code. It's well written and well commented.

Cheers!

EDIT:

As biesior commented: to show human readable pretty messages with different languages you have to check how play works I18N out here

To be thorough you're probably going to have to deal with I18N. It's not hard at all to get it all working. After reading the documentation you may still find yourself a bit consufed. I'll give you a little push. Add a messages file to your conf folder and you can copy its content from here. That way you'll have more control over the default messages. Now, in your view, you should be able to do something like that:

eventForm.errors("name").foreach { error =>
          <div>@Messages(error.message, error.args: _*)</div>
}

For instance, if error.message were error.invalid it would show the message previously defined in the conf/messages file Invalid value. args define some arguments that your error message may handle. For instance, if you were handling an error.min, an arg could be the minimum value required. In your message you just have to follow the {n} pattern, where n is the order of your argument.

Of course, you're able to define your own messages like that:

error.futureBirthday=Are you sure you're born in the future? Oowww hay, we got ourselves a time traveler!

And in your controller you could check your form like that (just one line of code to show you the feeling of it)

"year" -> number.verifying("error.furtureBirthday", number <= 2012) // 2012 being the current year

If you want to play around with languages, just follow the documentation.

Cheers, again!

like image 161
wleao Avatar answered Sep 22 '22 23:09

wleao


As you said yourself, message is a member of FormError, but you have an Option[FormError]. You could use

eventForm("name").error.map(_.message).getOrElse("")

That gives you the message, if there is an error, and "" if there isn't.

like image 39
Kim Stebel Avatar answered Sep 21 '22 23:09

Kim Stebel