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

New features

You can see the full changelog here.

Play 2.5.12 and Bootstrap 4 (alpha) support

The project has been split to give support for Bootstrap 4 alpha. So now there are four 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.

Please, check the documentation for Bootstrap 4 Alpha.

Features

Simple to use

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

@import b3.vertical.fieldConstructor  // Declares a vertical field constructor as default

@b3.form(routes.Application.login) {
  @b3.email( loginForm("email"), '_label -> "Email", 'placeholder -> "example@mail.com" )
  @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.

@import b3.vertical.fieldConstructor  // Declares a vertical field constructor as default

@b3.form(routes.Application.index) {
  @b3.email( fooForm("email"), '_label -> "Email", 'placeholder -> "example@mail.com" )
  @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 }
}
@implicitFieldConstructor = @{ b3.horizontal.fieldConstructor("col-md-2", "col-md-10") }  // Declares a horizontal field constructor as default

@b3.form(routes.Application.index) {
  @b3.email( fooForm("email"), '_label -> "Email", 'placeholder -> "example@mail.com" )
  @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 }
}
@import b3.inline.fieldConstructor  // Declares a inline field constructor as default

@b3.form(routes.Application.index) {
  @b3.email( fooForm("email"), '_hiddenLabel -> "Email", 'placeholder -> "example@mail.com" )
  @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 }
}
@import b3.vertical.fieldConstructor  // Declares a vertical field constructor as default

@b3.inline.form(routes.Application.index) { implicit ifc =>  // An inline form instead of the default one
  @b3.email( fooForm("email"), '_hiddenLabel -> "Email", 'placeholder -> "example@mail.com" )
  @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 }
}
@b3.form(routes.Application.index) {  // Uses the default field constructor (vertical in that case)
  @b3.text( fooForm("foo"), '_label -> "Foo", 'placeholder -> "Foo placeholder..." )
  @b3.text( fooForm("bar"), '_label -> "Bar", 'placeholder -> "Bar placeholder..." )
  @b3.submit('class -> "btn btn-default"){ Send }
}

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" )
@b3.email( 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
to
Select a date range from 10-11-2014
@b3.multiCheckbox(
  (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 -> "field.username.help" )
@b3.email( loginForm("email"), '_label -> "field.email.label", 'placeholder -> "field.email.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.

Installation

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 "https://oss.sonatype.org/content/repositories/snapshots/"

libraryDependencies ++= Seq(
  "com.adrianhurt" %% "play-bootstrap" % "1.1-P25-B3"
)

Note the play-bootstrap has filters, Bootstrap and jQuery as dependencies, so they are included automatically. Specifically, it adds the following dependencies for you:

filters,
"org.webjars" % "bootstrap" % "3.3.7",
"org.webjars" % "jquery" % "2.2.3"

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.1-P25-B3" 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.1-P25-B3 play-bootstrap Play 2.5.6 Bootstrap 3.3.7 jQuery 2.2.3 See 1.1-P25-B3 docs
1.1-P24-B3 play-bootstrap Play 2.4.8 Bootstrap 3.3.7 jQuery 2.2.3 See 1.1-P24-B3 docs
1.1-P25-B4 play-bootstrap Play 2.5.6 Bootstrap 4.0.0-alpha jQuery 2.2.3 See 1.1-P25-B4 docs
1.1-P24-B4 play-bootstrap Play 2.4.8 Bootstrap 4.0.0-alpha jQuery 2.2.3 See 1.1-P24-B4 docs
1.1.1-P25-B3-SNAPSHOT play-bootstrap Play 2.5.12 Bootstrap 3.3.7 jQuery 3.3.1 See 1.1.1-P25-B3 docs
1.1.1-P24-B3-SNAPSHOT play-bootstrap Play 2.4.10 Bootstrap 3.3.7 jQuery 3.3.1 See 1.1.1-P24-B3 docs
1.1.1-P25-B4-SNAPSHOT play-bootstrap Play 2.5.12 Bootstrap 4.0.0-alpha.5 jQuery 3.3.1 See 1.1.1-P25-B4 docs
1.1.1-P24-B4-SNAPSHOT play-bootstrap Play 2.4.10 Bootstrap 4.0.0-alpha.5 jQuery 3.3.1 See 1.1.1-P24-B4 docs

The previous versions are within the artifact play-bootstrap3:

"com.adrianhurt" %% "play-bootstrap3" % "0.4.5-P24"

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

Examples

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:

Customization

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.