This is a collection of input helpers and field constructors for Play Framework to render Bootstrap Forms HTML code.

Buy me a coffee Buy me a coffee

New features

You can see the full changelog here.

Parameterize your field constructors

Now you can add the params isCustom and withFeedbackTooltip (or withFeedbackIcons for Bootstrap 3) for rendering every input helper as "custom field" and with feedback tooltips.

Play 2.6.12 and Bootstrap 4 support

The project has been split to give support for Play 2.6.12 and Bootstrap 4. So there are 4 parallel versions depending on which version you need for Play Framework and Bootstrap:

Note! There is a selector on the topbar's right side for change between all versions.

Unfortunately, the new version breaks the way we usually imported field constructors. In the past we had the values fieldConstructor for “vertical”, “inline” and “clear” versions of field constructors. However, now all of them are functions due to now we can parameterize them.

In short, you should change the following:

@import b4.vertical.fieldConstructor

Into this:

@implicitFieldConstructor = @{ b4.vertical.fieldConstructor() }

And the same for B3 versions and for “inline” and “clear” field constructors as well.

Java support disclaimer

Regretfully, although this library should work correctly for Java version of Play Framework, I find myself in the position of not getting more support for it. However, any PR will be more than welcomed!


Simple to use

It tries to follow the same rules as the helper library from Play Framework.

@b3.vertical.form(routes.Application.login) { implicit vfc => loginForm("email"), '_label -> "Email", 'placeholder -> "" )
  @b3.password( loginForm("password"), '_label -> "Password", 'placeholder -> "Password" )
  @b3.checkbox( loginForm("remember"), '_text -> "Remember me", 'value -> true )
  @b3.submit('class -> "btn btn-default"){ Sign in }

Horizontal, vertical or inline forms

There is a different field constructor for each kind of form. Normally, you will declare one of them as default for each of your templates, but you can mix them if you want.

@b3.vertical.form(routes.Application.index) { implicit vfc => fooForm("email"), '_label -> "Email", 'placeholder -> "" )
  @b3.password( fooForm("password"), '_label -> "Password", 'placeholder -> "Password" )
  @b3.checkbox( fooForm("remember"), '_text -> "Remember me", 'value -> true )
  @b3.submit('class -> "btn btn-default"){ Sign in }
@b3.horizontal.form(routes.Application.index, "col-md-2", "col-md-10") { implicit hfc => fooForm("email"), '_label -> "Email", 'placeholder -> "" )
  @b3.password( fooForm("password"), '_label -> "Password", 'placeholder -> "Password" )
  @b3.checkbox( fooForm("remember"), '_text -> "Remember me", 'value -> true )
  @b3.submit('class -> "btn btn-default"){ Sign in }
@b3.inline.form(routes.Application.index) { implicit ifc => fooForm("email"), '_hiddenLabel -> "Email", 'placeholder -> "" )
  @b3.password( fooForm("password"), '_hiddenLabel -> "Password", 'placeholder -> "Password" )
  @b3.checkbox( fooForm("remember"), '_text -> "Remember me", 'value -> true )
  @b3.submit('class -> "btn btn-default"){ Sign in }

Every helper you need

Inputs, checkboxes, radio buttons, selects, input-groups, custom inputs, ... You have the essential input helpers you could need. But this library is for the community, so you can collaborate or ask for others.

See the list of available helpers here.

Coherence and consistency

Boolean attributes

Sometimes the HTML syntax could be confusing. For example, all of the following codes are equivalent:

<input type="text" name="foo" disabled>
<input type="text" name="foo" disabled="true">
<input type="text" name="foo" disabled="false">
<input type="text" name="foo" disabled="blah">

For that reason, b3 helpers will simply remove the attribute with false values and put "true" value for true ones. So you can do:

@b3.text( fooForm("foo"), '_label -> "A maybe disabled text", 'disabled -> maybeTrueFunction(...) )

See more about Boolean arguments.

Readonly attribute for checkboxes, radio buttons and selects

Another frustrating and typical situation occurs when you try to use the readonly attribute for checkboxes, radio buttons or selects. It isn't implemented, so you usually need to add an extra <input type="hidden"> if you need to send its value within your POST request. For that cases, b3 helpers for checkboxes, radio buttons and selects automatically add that input for you when the attribute readonly is present.

Additionally, in that cases, when you add the readonly attribute, b3 helpers will also add the disabled attribute. Then, Bootstrap will avoid their interactability.

See more About disabled and readonly attributes.

HTML5 data form validation

If a field has validation constraints they will be added automatically as HTML5 data form validation.

For example, if you have this form

val validationForm = Form(tuple(
  "username" -> nonEmptyText(maxLength = 20),
  "email" -> email,
  "age" -> number(min = 18, max = 99),
  "color" -> nonEmptyText.verifying(pattern("^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$".r))

The constraints will be automatically added as you can see here:

A username between 1 and 20 characters
From 18 to 99 years old
Format is #CCC or #CCCCCC
@b3.text( validationForm("username"), '_label -> "Username", '_help -> "A username between 1 and 20 characters" ) validationForm("email"), '_label -> "Email" )
@b3.number( validationForm("age"), '_label -> "Age", '_help -> "From 18 to 99 years old" )
@b3.text( validationForm("color"), '_label -> "Hexadecimal color", '_help -> "Format is #CCC or #CCCCCC" )

See more about Validation arguments.

Multifield support

Sometimes you may need two or more fields within the same line in a horizontal or vertical form (for a set of checkboxes, a date range, ...). With the b3.multifield you will be able to create your own custom helpers in a very easy way.

Mark what you want
Select a date range from 10-11-2014
(fooForm("foo"), Map('_text -> "Foo")),
(fooForm("bar"), Map('_text -> "Bar")),
(fooForm("beer"), Map('_text -> "Beer"))
)('_label -> "Inline", 'class -> "multi-checkbox-list inline", '_help -> "Mark what you want")

@b3.datepicker( fooForm("dateStart"), 'value -> "15-11-2014" )(
fooForm("dateEnd"), 'value -> "31-12-2014" )(
'_label -> "Date range", "data-date-start-date" -> "10-11-2014", '_help -> "Select a date range from 10-11-2014" )

@b3.textWithCheckbox( fooForm("foo"), 'placeholder -> "a foo value" )( fooForm("fooSelected") )('_label -> "New task" )

Note: these helpers (b3.multiCheckbox, b3.datepicker and b3.textWithCheckbox) are not part of the library, but here it is explained how to easily implement them (or just copy them).

See more about Multifield support.

Auto internationalization

Most of arguments used in helpers are automatically internationalized. So you can simply write:

@b3.text( loginForm("username"), '_label -> "field.username.label", '_help -> "" ) loginForm("email"), '_label -> "", 'placeholder -> "" )
@b3.password( loginForm("password"), '_label -> "field.pwd.label", 'placeholder -> "field.pwd.placeholder" )
@b3.checkbox( loginForm("remember"), '_text -> "field.remember", 'value -> true )

With ARIA attributes

The WAI-ARIA attributes are a very helpful tool for accesibility. However we know it could be difficult and boring to integrate it everywhere within your web. Because of that, the library will do automatically for you for any field constructor.

See more about ARIA attributes support.


From version 1.2 for Play 2.5 or Play 2.6

You only need to add it as a dependency in your build.sbt file.

// Resolver is needed only for SNAPSHOT versions
resolvers += "Sonatype OSS Snapshots" at ""

libraryDependencies ++= Seq(
  "com.adrianhurt" %% "play-bootstrap" % "1.4-P26-B4-SNAPSHOT"

There are different versions of the library depending on the which version of Play Framework and Bootstrap you need:

Version Artifact Play version Documentation
1.4-P26-B4-SNAPSHOT play-bootstrap Play 2.6.12 See 1.4-P26-B4 docs
1.4-P25-B4-SNAPSHOT play-bootstrap Play 2.5.16 See 1.4-P25-B4 docs
1.4-P26-B3-SNAPSHOT play-bootstrap Play 2.6.12 See 1.4-P26-B3 docs
1.4-P25-B3-SNAPSHOT play-bootstrap Play 2.5.16 See 1.4-P25-B3 docs
1.3-P26-B4-SNAPSHOT play-bootstrap Play 2.6.12 See 1.3-P26-B4 docs
1.3-P25-B4-SNAPSHOT play-bootstrap Play 2.5.16 See 1.3-P25-B4 docs
1.3-P26-B3-SNAPSHOT play-bootstrap Play 2.6.12 See 1.3-P26-B3 docs
1.3-P25-B3-SNAPSHOT play-bootstrap Play 2.5.16 See 1.3-P25-B3 docs

You can check the change log here to see all versions.

Prior to version 1.2 or versions for Play 2.4

For versions prior to 1.2 or for Play 2.4, play-bootstrap has filters, Bootstrap and jQuery as dependencies, so they are included automatically. Specifically, it adds the following dependencies for you:

"org.webjars" % "bootstrap" % "3.3.7",
"org.webjars" % "jquery" % "3.2.1"

You can use different versions of jQuery or even Bootstrap. For example, if you prefer to use jQuery 2.1.0:

"com.adrianhurt" %% "play-bootstrap" % "1.4-P26-B4-SNAPSHOT" exclude("org.webjars", "jquery"),
"org.webjars" % "jquery" % "2.1.0"

There are different versions of the library depending on the which version of Play Framework and Bootstrap you need:

Version Artifact Play version Added dependencies Documentation
1.3-P24-B4-SNAPSHOT play-bootstrap Play 2.4.11 Bootstrap 4.0.0 jQuery 3.3.1 See 1.3-P24-B4 docs
1.3-P24-B3-SNAPSHOT play-bootstrap Play 2.4.11 Bootstrap 3.3.7 jQuery 3.3.1 See 1.3-P24-B3 docs

You can check the change log here to see all versions.


This web is an example. You can see on the top menu an example of each kind of form ( vertical, horizontal, inline) and one more for a single view with different mixed forms.

You can check the whole code on Github.

More examples:


This is a very simple library, and you have all the code on Github. So you can use it as inspiration and create your own field constructors and/or helpers.

Change Log

You can check the change log here.