Reputation: 99
I am struggling with Scala & Play a bit. I have this book class in my model
class Book(identifier: Int, title1: String, price1: Int, author1: String) {
val id: Int = identifier
val title: String = title1
var price: Int = price1
val author: String = author1
override def toString: String = s" $title written by $author"
}
In my BooksController class I am defining Basic CRUD operations. I wanted to do some magic using the FormFactory class which I am injecting.
import javax.inject._
import play.api.mvc._
import model.Book
import model.BookSet
import play.data._
import scala.collection.mutable.HashMap
@Singleton
class BooksController @Inject()(cc: ControllerComponents, formFactory: FormFactory) (implicit assetsFinder: AssetsFinder)
extends AbstractController(cc) {
//show a form
def create = {
val bookform: Form[Book] = formFactory.form(classOf[Book])
Ok(views.html.bookstore.create(bookform))
}
//show all books
def index = Action {
val map: HashMap[Int, Book] = BookSet.bookMap
Ok(views.html.bookstore.bookindex(map))
}
This is my bookstore.create scala.html file
@import model.Book
@import helper._
@(bookForm: Form[Book])
<html>
<head>
<title>Create Book </title>
</head>
<body>
<h1> Create Book</h1>
@helper.form( action = routes.BooksController.save() ){
@helper.inputText(bookForm("id"))
@helper.inputText(bookForm("title"))
@helper.inputText(bookForm("price"))
@helper.inputText(bookForm("author"))
<input type="submit" value="Create Book">
}
</body>
</html>
These are troublesome lines of code:
val bookform: Form[Book] = formFactory.form(classOf[Book])
Ok(views.html.bookstore.create(bookform))
On the second line IntelliJ informs me of Type mismatch, expected play.api.data.Form[model.Book], actual play.data.Form[model.Book]
I've tried fixing this by adding the follwing line to html but it results in an error (probably caused by the helper class)
@import play.data.Form
I've also tried passing the play.api.data.Form from the factory using asInstanceOf[]:
val bookform: Form[Book] = formFactory.form(classOf[Book])
Ok(views.html.bookstore.create(bookform.asInstanceOf[play.api.data.Form[Book]]))
After trying this i got the error during compilation: An implicit MessagesProvider instance was not found. P lease see https://www.playframework.com/documentation/2.6.x/ScalaForms#Passing-MessagesProvider-to-Form-Helpers [error] @helper.inputText(bookForm("title"))
It basically repeats for every field. So I've followed the scala docs Option 2 and added an Injection and implicit Request to the Controller as well as the implicit Request to html file. Still getting the same error
At this point I feel helpless so thats why I am asking the question. Is it acctually possible to use use play.data.FormFactory with a helper class? Unfourtunately play.api.data package doesn't provide it's own FormFactory. I feel like there is an obvious solution I am just missing. Thanks for patience
Upvotes: 0
Views: 270
Reputation: 992
I think at first glance, FormFactory
was never intended for Scala, only Java. I could be wrong about that, but I have never used it in Scala.
If you are willing to try the following you might have an easier time:
Change your Book
simply to:
case class Book(identifier: Int, title: String, price: Int, author: String)
Create a Form that looks like this:
val bookForm = Form(
mapping(
"id" -> number,
"title" -> nonEmptyText,
"price" -> number,
"author" -> nonEmptyText
)(Book.apply)(Book.unapply)
)
Then your Controller
can look something like the following:
@Singleton
class BooksController @Inject()(cc: ControllerComponents)
(implicit assetsFinder: AssetsFinder)
extends AbstractController(cc) {
//show a form
def create = {
Ok(views.html.bookstore.create(bookForm))
}
//show all books
def index = Action {
val map: HashMap[Int, Book] = BookSet.bookMap
Ok(views.html.bookstore.bookindex(map))
}
}
Unsure about AssetsFinder
here, but you may have a reason, so I left it in the example. ;)
Upvotes: 0