Creating new helpers is useful for adding or customizing the input structure of a field, but you may need your own field constructor, with another form-group
structure. Let's see another example. Imagine that you want a vertical form but with any help information (errors, constraints and help messages) at a side panel. Something like this:
<div class="my-form-group form-group has-danger" id="foo_field">
<div class="field-container">
<label for="foo">Email</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">@</span>
</div>
<input type="email" id="foo" name="foo" value="" aria-describedby="foo_info_0 foo_error_0" aria-invalid="true" class="form-control" placeholder="example@mail.com">
</div>
</div>
<div class="alert alert-danger" role="alert">
<ul>
<li><span id="foo_error_0" class="help-error"><i class="fa fa-remove"></i> And error occurred!</span></li>
<li><span id="foo_info_0" class="help-info"><i class="fa fa-warning-sign"></i> Maximum length: 10</span></li>
</ul>
</div>
</div>
We are going to make it easy. Let's going to copy the files for the vertical field constructor and modify them. You can see the files
here. So create a folder views/b4/my/vertical
and copy there the files
bsFieldConstructor.scala.html,
bsFormGroup.scala.html and
package.scala.
Modify bsFieldConstructor.scala.html
and bsFormGroup.scala.html
to get the functionality you want. For this example, the first one would be re-written to something like this:
@(fieldInfo: b4.B4FieldInfo, inputHtml: Html)(implicit messages: Messages)
@alertStatus = @{
if (fieldInfo.hasErrors)
"alert-danger"
else if (b4.ArgsMap.isTrue(fieldInfo.argsMap, '_success))
"alert-success"
else
"alert-info"
}
<div class="my-form-group form-group @fieldInfo.argsMap.get('_class) @fieldInfo.status.map("has-"+_)" id="@fieldInfo.idFormField">
<div class="field-container">
@fieldInfo.labelOpt.map { label =>
<label@if(fieldInfo.hideLabel){ class="sr-only"} @if(fieldInfo.withLabelFor){for="@fieldInfo.id"}>@bs.Args.msg(label)(messages)</label>
}
@inputHtml
</div>
<div class="alert @alertStatus" role="alert">
<ul>
@fieldInfo.feedbackInfos.map { case (id, text) =>
<li><span id="@id" class="form-control-feedback">@bs.Args.msg(text)(messages)</span></li>
}
@fieldInfo.helpInfos.map { case (id, text) =>
<li><span id="@id" class="form-text text-muted">@bs.Args.msg(text)(messages)</span></li>
}
</ul>
</div>
</div>
Do the same with bsFormGroup.scala.html
. You can check them at the Github repository here:
bsFieldConstructor.scala.html and
bsFormGroup.scala.html.
Finally, the modifications for this examples to package.scala
are minimal:
package views.html.b4
to package views.html.b4.my
views.html.b4._
formClass
to "form-my-vertical"
And that's all, you now can use your own field constructor as any other with:
@import b4.my.vertical.fieldConstructor // Declare it as default
@b4.my.email( fooForm("foo"), '_label -> "Email", '_error -> "And error occurred!", '_showConstraints -> true, 'placeholder -> "example@mail.com" )
Or even using it for specific forms:
@b4.my.vertical.form(routes.Application.extendIt) { implicit myfc =>
@b4.my.email( fooForm("foo"), '_label -> "Email", '_error -> "And error occurred!", '_showConstraints -> true, 'placeholder -> "example@mail.com" )
}