Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create multiple custom fields in Play Framework?

I am trying to build multiple custom fields.

Using this article as a reference.

After creating MyHelpers.

object MyHelpers {

  //This '.f' is kinda mysterious/magic...
  implicit val myFields = FieldConstructor(myFieldConstructorTemplate.f)    

}

I import on my .scala.html

@import MyHelpers._

Then magically when I do

@inputText(myForm("username"))

It's going to use my constructor on MyHelpers

But, how would I create multiple constructors, so I could create different input types, like:

@inputText(myForm("username"))
@inputDate(myForm("birth"))

How would I implement that?

Firstly, I am new to Scala (have been reading books and articles and load of things about Scala for quite some time but hardly coded something). I am sorry for such question, but scala makes it hard to learn Play, looks like you need to master Scala before, so you can assimilate Play or even understand how it is built. Documentation doesn't help too much in these cases.

like image 557
mrcaramori Avatar asked Jun 21 '13 20:06

mrcaramori


2 Answers

Another way to do this is to create multiple fields in a scala object (a different file), and then import this object in your views. The rest will be easy to follow.

First: Create a view for the field you wish to construct. Let's call it textinputgroup.scala.html

It will contain this code

@(elements: helper.FieldElements, text: String)
<div class="form-group input-group if(@elements.hasErrors) {error}">
   <span class="input-group-addon">@text</span>
   @elements.input
   <span class="errors">@elements.errors.mkString(", ")</span>
</div>

Then: Create your object helper. Let's call it bootstrap.scala And put inside of it the fields that you want to create. (You can put bootstrap.scala and textinput.scala.html in the same folder under the 'views' directory)

package views
import views.html.helper._

object bootstrap {
  implicit val addressinputgroup = new FieldConstructor {
    def apply(elements: FieldElements) = textinputgroup(elements, "@")
  }
  implicit val passwordinputgroup = new FieldConstructor {
    def apply(elements: FieldElements) = textinputgroup(elements, "*")
  }
}

And Finally: Import and use this object in your views.

@(signin: Form[forms.Signin]) /* Insert here your real form definition */
@import helper._
@import views.bootstrap._

/* Inside the body */
@helper.form(action = routes.Auth.submit()) {
  @inputText(signin("email"), 'class -> "form-control", 'placeholder -> "Email")(addressinputgroup, implicitly[Lang])
  @inputPassword(signin("password"), 'class -> "form-control", 'placeholder -> "Password")(passwordinputgroup, implicitly[Lang])
  <button class="btn btn-default" type="submit">Sign Up &raquo;</button>
}

I made some more examples in this repository to create multiple fields using Bootstrap (multipleFieldConstructor) and Semantic-UI (semanticuiformhelper) frameworks. Check them out.

like image 89
Firas Avatar answered Oct 16 '22 06:10

Firas


The answer depends on what you mean by "different input types". If you are wanting your username field to be like a regular text box and your birth to be something like a date picker then you don't really need to mess with field constructors, you may just need a custom "input helper".

The input helpers are the scala templates that define the HTML input element itself. In the case of a date-picker you would have the input text field and it might also include the little calendar graphic to popup the calendar or something.

The field constructor is all of the HTML that goes around the HTML input element that the helper generated. This includes any divs to make it fit the structure of your page and also generates help/error text associated with the field.

Input Helpers

My guess is that what you're really wanting to customize is an input helper. If @inputDate isn't doing what you need then you can create your own. Take a look at Play's built-in input helpers on GitHub for examples:

https://github.com/playframework/Play20/tree/2.0.x/framework/src/play/src/main/scala/views/helper

Field Constructors

If you are wanting multiple field constructors then that's possible too. You can actually define as many as you want and select them on a per field basis. On the same documentation page you linked it shows an alternate way of defining the field constructor directly on your view.

@implicitField = @{ FieldConstructor(myFieldConstructorTemplate.f) }

This will be your default field constructor (because it starts with @implicit? I don't fully understand this part). To define a second one just copy that line but call the variable something different. This is something I'm using in a project:

@selectFieldConstructor = @{ FieldConstructor(entryFormFieldConstructor.f) }

And to use it:

@select(
  myForm("gender"),
  ...
)(handler = selectFieldConstructor, implicitly[Lang])

Hope this helps.

like image 21
estmatic Avatar answered Oct 16 '22 06:10

estmatic