AKnox
AKnox

Reputation: 2635

Play framework form submit isn't passing validation

I am new to scala and type-safe languages so I could be overlooking something basic. That said here's my problem.

Goal: I want to submit a form that is just one text input, and does not mirror my case class. It is going to end up as type: String

Issue: Can't get into success from fold

I have a form on the frontend that I opted to write in html instead of play's form helpers (willing to change if this is the issue)

<form method="POST" action="@routes.Application.shorten()">
  <input id="urlLong" name="urlLong" type="text" placeholder="http://www.google.com/" class="span4"/>
  <div class="form-actions">
    <button type="reset" class="btn">Reset</button>
    <button type="submit" class="btn btn-primary pull-right"><span class="icon-random"></span> Shrtn It!</button>
  </div>
</form>

The controller that is handling the post action looks like this:

import ...

object Application extends Controller {

  val newUrlForm = Form(
    "urlLong" -> text
  )

  def shorten = Action { implicit request =>
    val urlLong = newUrlForm.bindFromRequest.get

    newUrlForm.fold(
      hasErrors = { form =>
        val message = "Somethings gone terribly wrong"
        Redirect(routes.Application.dash()).flashing("error" -> message)
    },

    success = { form =>
      val message = "Woot it was successfully added!"
      Redirect(routes.Application.dash()).flashing("success" -> message)
    }
  }
  ...
}

I was trying to follow / modify the tutorial in the Play for Scala book, but they match their form to a case class, and Play's tutorial is a bit off from my use case as well. Along with your answer if you could include how you figured it out, that would be really useful so I can troubleshoot on my own better.

Also if it matters I am using intellij idea as my ide

Upvotes: 0

Views: 2204

Answers (2)

AKnox
AKnox

Reputation: 2635

What I ended up with:

def shorten = Action { implicit request =>
  newUrlForm.bindFromRequest.fold(
    hasErrors = { form =>
      val message = "Somethings gone terribly wrong"
      Redirect(routes.Application.dash()).flashing("error" -> message)
    },

    success = { urlLong =>
      val message = "Woot it was successfully added!"
      Redirect(routes.Application.dash()).flashing("success" -> message)
    }
  )
}

Not sure I really understand what I was doing wrong, but this code based off of mericano1 's answer ended up working as well. It seems like previously i was getting the urlLong val out of the form and then folding the form, where as this folds the form directly, and extracts the val of urlLong in the process.

Also I'm not sure why the arguments for fold are documented differently.

Upvotes: 0

mericano1
mericano1

Reputation: 2913

You need to call the fold method on form.bindFromRequest. From the documentation > Handling binding failure

loginForm.bindFromRequest.fold(
  formWithErrors => // binding failure, you retrieve the form containing errors,
  value => // binding success, you get the actual value 
)

Also you can use the single Mapping construct for a single field

Form(
  single(
    "email" -> email
  )
)

Upvotes: 1

Related Questions