Documentation

You are viewing the documentation for the 2.8.0-M1 development release. The latest stable release series is 3.0.x.

§Form template helpers

Play provides several helpers to help you render form fields in HTML templates.

§Creating a <form> tag

The first helper creates the <form> tag. It is a pretty simple helper that automatically sets the action and method tag parameters according to the reverse route you pass in:

@helper.form(action = routes.Application.submit()) {

}

You can also pass an extra set of parameters that will be added to the generated HTML:

@helper.form(action = routes.Application.submit(), 'id -> "myForm") {

}

§Rendering an <input> element

There are several input helpers in the views.html.helper package. You feed them with a form field, and they display the corresponding HTML form control, with a populated value, constraints and errors:

@(myForm: play.data.Form[User])(implicit messages: play.i18n.Messages)

@helper.form(action = routes.Application.submit()) {

    @helper.inputText(myForm("email"))

    @helper.inputPassword(myForm("password"))

}

As for the form helper, you can specify an extra set of parameters that will be added to the generated HTML:

@helper.inputText(myForm("email"), 'id -> "email", 'size -> 30)

Note: All extra parameters will be added to the generated HTML, except for ones whose name starts with the _ character. Arguments starting with an underscore are reserved for field constructor argument (which we will see later).

§Handling HTML input creation yourself

There is also a more generic input helper that let you code the desired HTML result:

@helper.input(myForm("email")) { (id, name, value, args) =>
    <input type="date" name="@name" id="@id" @toHtmlArgs(args)>
}

§Field constructors

A rendered field does not only consist of an <input> tag, but may also need a <label> and a bunch of other tags used by your CSS framework to decorate the field.

All input helpers take an implicit FieldConstructor that handles this part. The default one (used if there are no other field constructors available in the scope), generates HTML like:

<dl class="error" id="email_field">
    <dt><label for="email">Email:</label></dt>
    <dd><input type="text" name="email" id="email" value=""></dd>
    <dd class="error">This field is required!</dd>
    <dd class="error">Another error</dd>
    <dd class="info">Required</dd>
    <dd class="info">Another constraint</dd>
</dl>

This default field constructor supports additional options you can pass in the input helper arguments:

'_label -> "Custom label"
'_id -> "idForTheTopDlElement"
'_help -> "Custom help"
'_showConstraints -> false
'_error -> "Force an error"
'_showErrors -> false

§Writing your own field constructor

Often you will need to write your own field constructor. Start by writing a template like:

@(elements: helper.FieldElements)

<div class="@if(elements.hasErrors) {error}">
<label for="@elements.id">@elements.label</label>
<div class="input">
    @elements.input
    <span class="errors">@elements.errors.mkString(", ")</span>
    <span class="help">@elements.infos.mkString(", ")</span>
</div>
</div>

Save it in views/ and name myFieldConstructorTemplate.scala.html

Note: This is just a sample. You can make it as complicated as you need. You have also access to the original field using @elements.field.

Now create a FieldConstructor somewhere, using:

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

@inputText(myForm("email"))

§Handling repeated values

The last helper makes it easier to generate inputs for repeated values. Suppose you have this kind of form definition:

public class UserForm {

  private String name;
  private List<String> emails;

  public void setName(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }

  public void setEmails(List<String> emails) {
    this.emails = emails;
  }

  public List<String> getEmails() {
    return emails;
  }
}

When you are using repeated data like this, there are two alternatives for sending the form values in the HTTP request. First, you can suffix the parameter with an empty bracket pair, as in “emails[]”. This parameter can then be repeated in the standard way, as in http://foo.com/request?emails[][email protected]&emails[][email protected]. Alternatively, the client can explicitly name the parameters uniquely with array subscripts, as in emails[0], emails[1], emails[2], and so on. This approach also allows you to maintain the order of a sequence of inputs.

Now you have to generate as many inputs for the emails field as the form contains. Just use the repeat helper for that:

@helper.inputText(userForm("name"))

@helper.repeat(userForm("emails"), min = 1) { emailField =>

    @helper.inputText(emailField)

}

Use the min parameter to display a minimum number of fields, even if the corresponding form data are empty.

If you want to access the index of the fields you can use the repeatWithIndex helper instead:

@helper.repeatWithIndex(userForm("emails"), min = 1) { (emailField, index) =>

    @helper.inputText(emailField, '_label -> ("email #" + index))

}

Next: Protecting against CSRF