Temak
Temak

Reputation: 3009

@Select with Int values in Scala Temlate

I'm using play-2.0.3.
I have a Map and want to populate dropdown-list with Int->String ( using something like @select).
I know that @select accepts only Seq[(String, String).
How can I overload this helper to accept Seq[(Int, String)] ?

I have tried to do the following:

  1. Copied source of the select.scala.html to views/mySelect.scala.html
  2. Edited it for my purposes.
@**
* Generate an HTML select.
*
* Example:
* {{{
* @select(field = myForm("isDone"), options = options("Yes","No"))
* }}}
*
* @param field The form field.
* @param args Set of extra attributes.
* @param handler The field constructor.
*@
@import helper._

@(field: Field, options: Seq[(Int,String)], args: (Symbol,Any)*)(implicit handler: FieldConstructor, lang: play.api.i18n.Lang)

@input(field, args:_*) { (id, name, value, htmlArgs) =>
    <select id="@id" name="@name" @toHtmlArgs(htmlArgs)>
    @args.toMap.get('_default).map { defaultValue =>
        <option class="blank" value="">@defaultValue</option>
    }
    @options.map { v =>
        <option value="@v._1" @(if(value == Some(v._1)) "selected" else "")>@v._2</option>
    }
    </select>
}

But it seems no to work.

Play says

')' expected but identifier found. 

in the line

@(field: Field, options: Seq[(Int,String)], args: (Symbol,Any)*)(implicit handler: FieldConstructor, lang: play.api.i18n.Lang) 

By the way what is * for after the (Symbol,Any) ?
Play doesn't like it. Even if I delete this *, then play says:

 not found: value field 

refering the same line.

Help me please.

Upvotes: 0

Views: 1889

Answers (2)

Temak
Temak

Reputation: 3009

I have found the solution.

@**
* file views/mySelect.scala.html 
*
* Generate an HTML select.
*
* Example:
* {{{
* @select(field = myForm("isDone"), options = options("Yes","No"))
* }}}
*
* @param field The form field.
* @param args Set of extra attributes.
* @param handler The field constructor.
*@


@(field: Field, listOptions: Map[Integer,String], args: (Symbol,Any)*)(implicit handler: views.html.helper.FieldConstructor, lang: play.api.i18n.Lang)
@import helper._
@input(field, args:_*) { (id, name, value, htmlArgs) =>
    <select id="@id" name="@name" @toHtmlArgs(htmlArgs)>
    @args.toMap.get('_default).map { defaultValue =>
        <option class="blank" value="">@defaultValue</option>
    }
    @listOptions.map { v =>
        <option value="@v._1" @(if(value == Some(v._1)) "selected" else "")>@v._2</option>
    }
    </select>
}
  • (Symbol,Any)* means "Treat as vararg parameter". You use it when you have a variable argument function, like

    def varargfunc( argument : T* ) ...
    
  • now we can

    @import mySelect 
    

    and use it like

    @mySelect(
        userForm("room"), 
        rooms, @* Map<Integer, String>* rooms*@ 
        '_default -> Messages.get("chooseRoom"),
        '_showConstraints -> false
        )
    
  • Yes, we should use @import only after function declaration (in function's body).

  • Don't use variable name

    options: Map[Integer,String]
    

    along with

    @import helper._ 
    

    Because it causes ambiguous sense of options, as it is also a function from views.html.helper

Upvotes: 0

user1411778
user1411778

Reputation: 461

Remove "@import helper._" . Every scala template file is a function in the background. The "@(field: Field, options: Seq[(Int,String)], args: (Symbol,Any)*)(implicit handler: FieldConstructor, lang: play.api.i18n.Lang)" line must be the first line.

Upvotes: 1

Related Questions