skip to Main Content

I have some sort of quiz system, where to user gets shown a question and several answer-options with radio-buttons.

But as I am using a helper for a inputRadioGroup that gets filled via a list, it does not look pretty anymore (like Twitter Bootstrap). The radiobuttons are inline, while they should be underneath each other. And actually I would like to change the icon to a prettier button.

This is how it looks at the moment:

Example

Therefore I tried to write my own custom form helper, but keep getting stuck. I find it frustratingly hard to understand the documentation for this:
https://www.playframework.com/documentation/2.3.x/JavaFormHelpers

First I created a new template named myFieldConstructorTemplate.scala.html

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

Saved it to the /views-folder. Then try to use it in my view class quiz.scala.html:

@import helper._
@import helper.twitterBootstrap._

@(questionList: List[Question], answerList: List[Answer], answerRadioForm: Form[Answer])

@helper.form(action = routes.Application.nextQuizPage(), 'id -> "answerRadioForm"){
    @helper.inputRadioGroup(
    answerRadioForm("Answer"),
    options = answerList.map(answer => answer.answerID.toString -> answer.answerText),
    '_label -> "Answer",
    '_error -> answerRadioForm("answerID").error.map(_.withMessage("select answer")))
<button type="submit" class="btn btn-default" value="Send">
    Next Question
</button>
}
@implicitField = @{ FieldConstructor(myFieldConstructorTemplate.f) }
@inputText(answerRadioForm("questionID"))

If I put this into my template, I get a not found: value implicitField-error.

So how can I manage to change the appearance of my radiobuttons to underneath and looking like Twitter Bootstrap?

[EDIT1]: I have changed the order of the imports to the suggested version:

@(questionList: List[Question], answerList: List[Answer], answerRadioForm: Form[Answer])

@import helper._
@implicitField = @{ FieldConstructor(myFieldConstructorTemplate.f) }
@import helper.twitterBootstrap._

I get this error then:

ambiguous implicit values: 
both method implicitField of type => views.html.helper.FieldConstructor 
and value twitterBootstrapField in package twitterBootstrap of type 
=> views.html.helper.FieldConstructor match expected type 
views.html.helper.FieldConstructor

I think this has to do with the way I import the answers into the radiobuttons?

[EDIT2]:
The order of the imports is now:

@(questionList: List[Question], answerList: List[Answer], answerRadioForm: Form[Answer])

@import models.Question
@import models.Answer

@import helper._
@implicitField = @{ FieldConstructor(myFieldConstructorTemplate.f) }

With this, the program compiles. BUT the radiobuttons still look the same. So I tried to change the design, which does not quite work. It looks now like all the radiobuttons are melted into a single one:

Monty Python

Here is my template class myFieldConstructorTemplate.scala.html:

@(elements: helper.FieldElements)

<div class="btn-group", data-toggle="buttons">
<label for="@elements.id">@elements.label</label>
<div class="input">
    <label class="btn btn-primary">
    @elements.input
    <span class="errors">@elements.errors.mkString(", ")</span>
    <span class="help">@elements.infos.mkString(", ")</span>
</label>
</div>
</div>

[EDIT3]: I have changed my class according to the last answer, but still the radiobuttons are melted into each other. So I want to point out that I am not fixated on using the inputRadioGroup from the playframework helper, if there is another solution that works the same and looks almost like bootstrap, I would gladly use that. It seems that changing the helper isnt that easy / intuitive. I appreciate any form of help!

3

Answers


  1. Move the implicitField-definition to the top of the file:

    @(questionList: List[Question], answerList: List[Answer], answerRadioForm: Form[Answer])
    @import helper._
    @implicitField = @{ FieldConstructor(myFieldConstructorTemplate.f) }
    @import helper.twitterBootstrap._
    
    @helper.form(action = routes.Application.nextQuizPage(), 'id -> "answerRadioForm"){
        @helper.inputRadioGroup(
        answerRadioForm("Answer"),
        options = answerList.map(answer => answer.answerID.toString -> answer.answerText),
        '_label -> "Answer",
        '_error -> answerRadioForm("answerID").error.map(_.withMessage("select answer")))
    <button type="submit" class="btn btn-default" value="Send">
        Next Question
    </button>
    }
    @inputText(answerRadioForm("questionID"))
    

    This makes sure the implicit value is available where it’s needed.

    Login or Signup to reply.
  2. Always keep params on top of template and remove the following import statement @import helper.twitterBootstrap._ this will conflict with your own field constructor.

    @(questionList: List[Question], answerList: List[Answer], answerRadioForm: Form[Answer])
    
    @import helper._
    @implicitField = @{ FieldConstructor(myFieldConstructorTemplate.f) }
    

    Hope it resolves your issue.

    Login or Signup to reply.
  3. The Twitter Bootstrap structure needs to be accurate.

    Wrap the btn-group class around the inputRadioGroup helper like so:

    <div class="btn-group" data-toggle="buttons">
    @helper.inputRadioGroup(
        answerRadioForm("Answer"),
        options = answerList.map(answer => answer.answerID.toString -> answer.answerText),
        '_label -> "Answer",
        '_error -> answerRadioForm("answerID").error.map(_.withMessage("select answer")))
    </div>  
    

    Then replace the template with:

    @(elements: helper.FieldElements)
    
    <label class="btn btn-primary">
        @elements.input @elements.label
    </label>
    
    <span class="errors">@elements.errors.mkString(", ")</span>
    <span class="help">@elements.infos.mkString(", ")</span>
    

    In general, perhaps it’d be of interest another way of doing it. When you use fooForm("myField"...), you can use fooForm("myField[@i]"...) in a for loop where @i is a counter going from 0 to however many inputs there are. Then you can yourself sketch out the full HTML instead of using implicit values.

    By the way, the documentation with the Scala version about all this has lots more information than the Java version. See here. It has more information on inputRadioGroup than the Java version of the documentation but still very useful reading for better understanding of all this.

    Some Play Bootstrap plugin has code available on GitHub that is also useful reading especially as it uses implicit values also.

    UPDATE

    Here’s a couple of GitHub projects showing how to achieve this:

    Screenshot of the result:

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search