如何创建具有未知(在构建时)列数的表

时间:2010-10-04 21:26:37

标签: scala lift

为简单起见,假设我有一个列表列表。我想显示一个html表,其中顶级列表的每个元素都有一行,并且该行中的每一列都是子列表的元素。

所以

List(List(1,2,3), List(4,5,6), List(7,8,9))

会导致html表格显示如下:

1     2     3
4     5     6
7     8     9
10    11    12

这是我的尝试(模板)

    <table>
        <lift:viewQuery.res2>
            <tr>
            <a:row>
                <td><a:num/></td>
            </a:row>
            </tr>
        </lift:viewQuery.res2>
    </table>

以及代码段中的相关方法:

def res2(in :NodeSeq) : NodeSeq = {
  val data = List(List(1,2,3), List(4,5,6), List(7,8,9), List(10,11,12))

  def bindChild(child : List[Int],in :NodeSeq) = {
    child.flatMap(c => Helpers.bind("a", in,
                                    "num" -> c.toString))
  }
  data.flatMap(childList => Helpers.bind("a", in,
                                         "row" -> bindChild(childList, in)))
}

当我转到页面时,它会给我以下错误:

error on line 28 at column 23: Namespace prefix a on row is not defined
error on line 29 at column 31: Namespace prefix a on num is not defined
error on line 34 at column 23: Namespace prefix a on row is not defined
error on line 35 at column 31: Namespace prefix a on num is not defined
...

有关处理此问题的最佳方法的任何想法吗?

2 个答案:

答案 0 :(得分:2)

如果您不需要特定于电梯的答案,那么这样的事情可以起作用

val data = List(List(1,2,3), List(4,5,6), List(7,8,9))
<table>{data.map(row => <tr>{row.map(col => <td>{col}</td>)}</tr>)}</table>

您的实际用例可能有点复杂,因此可能不适用。

答案 1 :(得分:2)

你很亲密。试试这个:

<table>
    <lift:viewQuery.res2>
        <a:row>
        <tr>
            <b:cell><td><cell:num/></td></b:cell>
        </tr>
        </a:row>
    </lift:viewQuery.res2>
</table>

对于你的片段:

def res2(in :NodeSeq) : NodeSeq = {
  import Helpers._
  val data = List(List(1,2,3), List(4,5,6), List(7,8,9), List(10,11,12))

  def cell(x: List[Int])(template: NodeSeq) = 
    x.flatMap{y: Int => bind("cell", template, "num" -> y) }
  def row(x: List[List[Int]])(template: NodeSeq) = 
    x.flatMap {y =>  bind("b", template, "cell" -> { x: NodeSeq => cell(y)(x)} ) }

  bind("a", in, "row" -> { x: NodeSeq => row(data)(x) })
}

我已经离开某些类型并且更加明确,所以你可以看到究竟发生了什么。您的问题是您在每个级别使用相同的模板in,而您想要做的是逐渐缩小模板范围。因此,在上面的模板中,我们希望<a:row>标记内的所有内容都针对列表中的每个顶级项重复,然后<b:cell>内的所有内容重复每个Int。这样做的方法是创建一个FuncBindParam,这是我们正在使用以下行:

 "row" -> { x: NodeSeq => row(data)(x) }

然后,Lift将传递包含在<a:row>标记内的xhtml作为curried函数的参数。并且在curried函数内部的flatMap调用会根据需要多次重复模板。