Play/Scala 模板块语句 HTML 带局部变量的输出语法
Play/Scala Template Block Statement HTML Output Syntax with Local Variable
好的,我已经为此苦苦挣扎了一段时间,并且花了很多时间尝试不同的事情来做一些我使用 PHP.
可以轻松完成的事情
我正在尝试遍历列表,同时在本地跟踪变量,同时吐出 HTML 试图填充 table。
尝试 #1:
@{
var curDate : Date = null
for(ind <- indicators){
if(curDate == null || !curDate.equals(ind.getFirstFound())){
curDate = ind.getFirstFound()
<tr><th colspan='5' class='day'>@(ind.getFirstFound())</th></tr>
<tr><th>Document ID</th><th>Value</th><th>Owner</th><th>Document Title / Comment</th></tr>
}
}
}
我也尝试使用 scala 块语句来允许我将 curDate 作为变量保留在创建的范围内。此块正确维护 curDate 状态,但不允许我向 DOM 输出任何内容。由于我未转义,随机抛出 HTML,我实际上并不期望它能编译,但它确实如此。尽管决策结构在服务器上正确执行,但此循环只是在 DOM 上放置任何内容。
我尝试使用 @Html('...')
进行转义,但产生了编译错误。
尝试#2:
大量 google 搜索让我找到了 "for comprehension":
@for(ind <- indicators; curDate = ind.getFirstFound()){
@if(curDate == null || !curDate.equals(ind.getFirstFound())){
@(curDate = ind.getFirstFound())
}
<tr><th colspan='5' class='day'>@(ind.getFirstFound())</th></tr>
<tr><th>Document ID</th><th>Value</th><th>Owner</th><th>Document Title / Comment</th></tr>
}
在这个块中没有 if 语句,这是我最接近做我真正想做的事情,但显然我不允许重新分配非引用类型,这就是为什么我希望尝试 #1 的引用curDate : Date = null
的声明会起作用。此尝试让我在页面上获得 HTML(同样,如果我删除嵌套的 if 语句)但没有让我获得
我的问题是,我该如何实现这个意图?我非常痛苦地意识到我缺乏 Scala 知识,Play 模板语法加剧了这种情况。我不知道该怎么做。
提前致谢!
Play 的模板语言非常适合函数式编程。使用可变状态可能可以实现您想要实现的目标,但您可能最好顺其自然,并使用功能性解决方案。
如果你想在函数式编程中的循环迭代之间保持状态,可以通过折叠来实现——你从某个状态开始,在每次迭代中,你得到前一个状态和下一个元素,然后你 return 基于这两件事的新状态。
所以,看看您的第一个解决方案,您尝试做的似乎只是打印一个元素,如果它的日期与前一个不同,对吗?另一种表达方式是您要过滤掉所有日期与前一个日期相同的元素。表示在折叠方面,我们将把元素折叠成一个序列(我们的初始状态),如果折叠序列的最后一个元素与当前元素的日期不同,我们添加它,否则我们忽略它。
我们的弃牌是这样的:
indicators.foldLeft(Vector.empty[Indicator]) { (collected, next) =>
if (collected.lastOption.forall(_.getFirstFound != next.getFirstFound)) {
collected :+ next
} else {
collected
}
}
只是为了解释上面的内容,我们折叠成 Vector
因为 Vector
有常数时间附加和最后,List
有 n 时间。如果 collected
中没有最后一个元素,forall
将 return 为真,否则,如果传入的 lambda 计算结果为真,则 return 为真。在 Scala 中,==
调用 .equals
(在进行空检查之后),因此您不需要在 Scala 中使用 .equals
。
因此,将其放入模板中:
@for(ind <- indicators.foldLeft(Vector.empty[Indicator]) { (collected, next) =>
if (collected.lastOption.forall(_.getFirstFound != next.getFirstFound)) {
collected :+ next
} else {
collected
}
}){
...
}
好的,我已经为此苦苦挣扎了一段时间,并且花了很多时间尝试不同的事情来做一些我使用 PHP.
可以轻松完成的事情我正在尝试遍历列表,同时在本地跟踪变量,同时吐出 HTML 试图填充 table。
尝试 #1:
@{
var curDate : Date = null
for(ind <- indicators){
if(curDate == null || !curDate.equals(ind.getFirstFound())){
curDate = ind.getFirstFound()
<tr><th colspan='5' class='day'>@(ind.getFirstFound())</th></tr>
<tr><th>Document ID</th><th>Value</th><th>Owner</th><th>Document Title / Comment</th></tr>
}
}
}
我也尝试使用 scala 块语句来允许我将 curDate 作为变量保留在创建的范围内。此块正确维护 curDate 状态,但不允许我向 DOM 输出任何内容。由于我未转义,随机抛出 HTML,我实际上并不期望它能编译,但它确实如此。尽管决策结构在服务器上正确执行,但此循环只是在 DOM 上放置任何内容。
我尝试使用 @Html('...')
进行转义,但产生了编译错误。
尝试#2:
大量 google 搜索让我找到了 "for comprehension":
@for(ind <- indicators; curDate = ind.getFirstFound()){
@if(curDate == null || !curDate.equals(ind.getFirstFound())){
@(curDate = ind.getFirstFound())
}
<tr><th colspan='5' class='day'>@(ind.getFirstFound())</th></tr>
<tr><th>Document ID</th><th>Value</th><th>Owner</th><th>Document Title / Comment</th></tr>
}
在这个块中没有 if 语句,这是我最接近做我真正想做的事情,但显然我不允许重新分配非引用类型,这就是为什么我希望尝试 #1 的引用curDate : Date = null
的声明会起作用。此尝试让我在页面上获得 HTML(同样,如果我删除嵌套的 if 语句)但没有让我获得
我的问题是,我该如何实现这个意图?我非常痛苦地意识到我缺乏 Scala 知识,Play 模板语法加剧了这种情况。我不知道该怎么做。
提前致谢!
Play 的模板语言非常适合函数式编程。使用可变状态可能可以实现您想要实现的目标,但您可能最好顺其自然,并使用功能性解决方案。
如果你想在函数式编程中的循环迭代之间保持状态,可以通过折叠来实现——你从某个状态开始,在每次迭代中,你得到前一个状态和下一个元素,然后你 return 基于这两件事的新状态。
所以,看看您的第一个解决方案,您尝试做的似乎只是打印一个元素,如果它的日期与前一个不同,对吗?另一种表达方式是您要过滤掉所有日期与前一个日期相同的元素。表示在折叠方面,我们将把元素折叠成一个序列(我们的初始状态),如果折叠序列的最后一个元素与当前元素的日期不同,我们添加它,否则我们忽略它。
我们的弃牌是这样的:
indicators.foldLeft(Vector.empty[Indicator]) { (collected, next) =>
if (collected.lastOption.forall(_.getFirstFound != next.getFirstFound)) {
collected :+ next
} else {
collected
}
}
只是为了解释上面的内容,我们折叠成 Vector
因为 Vector
有常数时间附加和最后,List
有 n 时间。如果 collected
中没有最后一个元素,forall
将 return 为真,否则,如果传入的 lambda 计算结果为真,则 return 为真。在 Scala 中,==
调用 .equals
(在进行空检查之后),因此您不需要在 Scala 中使用 .equals
。
因此,将其放入模板中:
@for(ind <- indicators.foldLeft(Vector.empty[Indicator]) { (collected, next) =>
if (collected.lastOption.forall(_.getFirstFound != next.getFirstFound)) {
collected :+ next
} else {
collected
}
}){
...
}