在Play中调用函数作为模板调用中的参数

时间:2017-11-23 20:27:49

标签: scala templates playframework twirl play-templates

在Play / Scala中;我很困惑为什么这不会编译:

   @(tabNames: Seq[String])

   @isActive(idx: Int) = {
       @if(idx < 1) {
           "active"
       } else {
           ""
       }
   }

   <ul class="nav nav-tabs">
       @for((tab, idx) <- tabNames.zipWithIndex) {
           @views.html.generic.navLi("tab" + idx.toString, tab, isActive(idx))
       }
   </ul>

错误如下:

  

发现:play.twirl.api.HtmlFormat.Appendable [错误](其中   扩展到)play.twirl.api.Html [error] required:String [error]
  @ views.html.generic.navLi(“tab”+ idx.toString,tab,isActive(idx))

它无法识别对模板调用中isActive的调用,而我尝试了多种变体,例如@isActive(idx)isActive(@idx) ${isActive(idx)}(按照建议here)等。此模板生成导航栏,传入标签名称并检查是否nav li应为active(由类名/ JS配置)。

在另一个模板调用中调用函数时,似乎语法必须不同 - 我无法正确理解。

2 个答案:

答案 0 :(得分:2)

Documentation区分了

  • 可重复使用的代码块
  • 可重复使用代码块

请注意

之间@用法的细微差别
@isActive(idx: Int) = {
  @if(...

@isActive(idx: Int) = @{
  if(...

可重用的纯代码块可以具有任意返回类型。在您的情况下,要将String作为返回类型,您可以写:

   @isActive(idx: Int) = @{
       if(idx < 1) {
           "active"
       } else {
           ""
       }
   }

答案 1 :(得分:1)

Play documentation is a little light in this area;虽然声明&#34;功能&#34;当然是可行和有用的。在一个旋转模板中,返回类型似乎被锁定(有效地)Html - 即你的&#34;块&#34; (正如文档中所述)必须呈现HTML。

如文档中所建议的,最快的解决方案是将逻辑重定位到Scala类中;对于这样简单的事情,object是完成这项工作的最简单方法,即:

package views

object ViewHelper {

  def isActive(idx: Int):String = {
    if(idx < 1) {
      "active"
    } else {
      ""
    }
  }
}

<ul class="nav nav-tabs">
   @for((tab, idx) <- tabNames.zipWithIndex) {
       @views.html.generic.navLi("tab" + idx.toString, tab, ViewHelper.isActive(idx))
   }
</ul>

这种方法的优点包括可测试性和可重用性。请注意避免被ViewHelper可以做的事情带走 - 数据库查找等在这里是个坏主意! : - )