Adding class to input in Play 2 custom FieldConstructor
Asked Answered
M

4

7

I am making a custom field constructor in Play 2:

@(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>

I need the input element to always have a particular class "my-class". How can I do this? The FieldElements class has an args member. I tried making a copy of the elements with " my-class" appended to the value associated with '_class in args, but this did not seem to affect the input element.

Mandamus answered 4/12, 2013 at 0:53 Comment(0)
A
3

One way for custom input in Play Framework is

@(elements: helper.FieldElements)
<div class="form-group @elements.args.get('_class) @if(elements.hasErrors) {has-error}" id="@elements.args.get('_id).getOrElse(elements.id + "_field")">

    @if(elements.hasName) {
        <label class="control-label" for="@elements.id">@elements.name</label>
    } else {
        <label class="control-label" for="@elements.id">@elements.label(elements.lang)</label>
    }

    @if(elements.input.toString().contains("class=")) {

        @Html(elements.input.toString().replaceFirst("(class=[\"'])", "$1form-control "))

    } else {

        @Html(elements.input.toString().replaceFirst("(<\\w+ )", "$1class=\"form-control\" "))

    }


    @elements.errors.map { error =>
        <p class="help-block">@error</p>
    }

    @elements.infos.map { info =>
        <span class="help-block">@info</span>
    }
</div>
Adjunct answered 26/3, 2015 at 10:9 Comment(0)
C
1

This should do the trick:

@inputText(myForm("fieldName"), 'class -> "my-class")

UPDATE:

Ok, you want to override the @element.input right? You can have a look at the source code and create your own tag (helper): https://github.com/playframework/playframework/blob/master/framework/src/play/src/main/scala/views/helper/inputText.scala.html

Cutlerr answered 4/12, 2013 at 12:22 Comment(1)
Thanks for your response. What you've done is actually what I want to avoid. I want all inputs to have the "my-class" class, so I am trying to create a custom FieldConstructor in order to avoid always manually adding my-class to every form element.Mandamus
I
1

In your Field constructor replace

@elements.input

with:

@Html(elements.input.body.dropRight(2)+"class='form-control'>")

this might not be the most correct One but It would do the job but watch for the text area this would need extra efforts.

Inferior answered 11/12, 2013 at 15:54 Comment(1)
This is a bad approach because it stops you from adding classes normally (ie, with 'class -> "class1 class2" in the input helper).Ufa
P
1

Based on Nguyen answer I created a more robust method that will only modify desired elements and will also reuse the regular expressions.

object Helper {
  import views.html.helper.FieldConstructor
  implicit val inlineBootstrapConstructor = FieldConstructor(fieldConstructorTemplate.f)

  val classRegex = "(?s)(<(?:input|textarea|select)[^>]*\\sclass=[\"'])".r
  val noClassRegex = "(?s)(<(?:input|textarea|select))((?:(?!\\sclass=\").+)>)".r

  def addClassValue(text: String, classValue: String) = {
    val str = classRegex.replaceFirstIn(text, s"$$1$classValue ")
    noClassRegex.replaceFirstIn(str, s"""$$1 class="$classValue"$$2""")
  }
}

The method is pretty straight forward, it tries to modify the class element of the first input, textarea or select HTML element and then it creates the class element if it doesn't already exist. You can add more elements to the input|textarea|select list if necessary. This works perfect for some bootstrap templates where you have to embed some elements in another div.

Then, in your template, simply import this method and call it with your class value:

@(elements : helper.FieldElements)

@import Helper.addClassValue

@input = @{ addClassValue(elements.input.toString(), "form-control") }

<div class="@if(elements.hasErrors) {error}">
    <label for="@elements.id">@elements.label</label>
    <div class="input">
        @Html(input)
        <span class="errors">@elements.errors.mkString(", ")</span>
        <span class="help">@elements.infos.mkString(", ")</span>
    </div>
</div>
Phippen answered 14/6, 2016 at 10:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.