2
votes

My form looks like:

case class PasswordData(currentPassword: String, newPassword: String, verifyPassword: String)

val passwordForm = Form(
  mapping(
  )(PasswordData.apply)(PasswordData.unapply) verifying("Passwords do not match", fields => fields match {
    case data => (data.newPassword == data.verifyPassword)
})
)

My controller action follows the usual pattern:

passwordForm.bindFromRequest.fold(
  error => {},
  form => {}
)

The problem I have now is I need to verify if the entered 'currentPassword' is the same as what is on the user's object.

userDao.getById(userId).password == form.currentPassword

But I can't do this because I am not sure how to pass int he userId to my form definition since it is dynamic.

i.e. I can't do it like:

"currentPassword" -> nonEmptyText.verifying(....)  // userId not in scope

Update

I am trying to display these errors also using (they don't currently display the error, I only see the ul tags).

 @if(form.hasGlobalErrors) {
    <ul>
        @form.errors.foreach { error =>
        <li>@error.message</li>
        }
    </ul>
    }
1
@m-z I think he is talking about password and re-password... - sarveshseri
Yup... he said that... Somehow missed it. - sarveshseri
Well... the user_id should be provided somehow... be it a hidden filed in form... or in user session. - sarveshseri
@m-z It isn't plain text, I tried to simplify the scenario as it doesn't really matter how I go about matching the password. I have the userId in my session object, but I can't pass it into the form since that is a val - Blankman

1 Answers

5
votes

Nothing is stopping you from making your passwordForm a def, where you can pass in a user model.

def passwordForm(user: User) = Form(
  mapping(
    "currentPassword" -> nonEmptyText.verifying("Incorrect password.", enteredPassword =>
       // some comparison with `enteredPassword` and the user
    ),
    ...
  )(PasswordData.apply)(PasswordData.unapply)
    .verifying("Passwords do not match", data => 
       data.newPassword == data.verifyPassword
    )
)


passwordForm(user).bindFromRequest.fold(
  error => ...,
  form => ...
)

Also, to print out the global errors in the view, they are accessed via globalErrors, and not the normal errors field. You should also use map instead of foreach. foreach returns Unit, which will not print anything to the view.

@if(form.hasGlobalErrors) {
    <ul>
        @form.globalErrors.map { error =>
          <li>@error.message</li>
        }
    </ul>
}