Snap:使用已编译的拼接渲染表

时间:2013-11-02 11:50:54

标签: haskell haskell-snap-framework heist

嗯,这是我努力克服的编译拼接的另一个障碍。 当我第一次使用原始解释的拼接时,我遇到了一些麻烦,现在我无法将其翻译成已编译的变体。

此处描述了原始问题:rendering a table

所以我需要构建这种结构:

map (\doc -> fmap (\f -> splice $ f at doc) fields ) documents

只是外部和内部循环,外部渲染原始数据和内部渲染单元格。这一切都在原始链接中描述。

它目前以解释模式实现,如下所示:

tableRawS raw = mapSplices (\f -> tableCellS $ T.pack $ at f raw) (tableFields table)
  where tableCellS cell = runChildrenWithText $ "table-cell" ## cell

tableBodyS = mapSplices (\d -> runChildrenWith $ raws d) documents
  where docID d = T.pack $ show $ valueAt "_id" d
        raws d = do "table-raw" ## tableRawS d
                    "raw-id" ## textSplice $ docID d

我一直在苦苦挣扎几天没有结果。这可能是由于缺乏对编译拼接API的理解。请帮忙!

修改

我没有为我的问题提供足够的细节。我设法获得的上述解释变体的最佳近似值是:

tableBody = manyWithSplices runChildren tableRaw $ lift documents
tableRaw doc = do "table-raw" ## manyWithSplices runChildren rawCell $ lift labels
                    where rawCell label = "table-cell" ## pureSplice . textSplice $ at label doc 
                  "table-rawid" ## pureSplice . textSplice $ at "_id" doc
                    where oid = T.pack . show. valueAt "_id"

它不起作用!问题是翻译原始渲染函数tableRaw。所以我会提供更多细节。 我输入tableBody的数据是一个类似Map的结构列表:

document = ["_id" =: 12345, "name" =: "pretty", "model" =: "cool", "size" =: "big"]

因此,要以原始方式提取数据,我需要映射标签列表

map (\l -> at l document) labels

我可以使用解释的varian执行此操作而不会出现问题。 tableRawS的解释示例由ducument参数化,但映射在[labels]上。我无法在编译变体中实现这一点。我需要tableRaw函数中的文档和标签列表,因此我可以将不同的单元拼接绑定到文档之外。这真的很痛苦。我不知道怎么做。无论我做什么,我最终都会使用tableRaw映射文档而不是映射标签列表。

基本上。我使用上面提到的文档结构从数据库中获取[文档],并从数据库中获取标签,其中

 labels = ["name", "model", "size"] -- table fields

我使用“at :: Label - > Value”从文档中获取数据 完成所有这些后,我该如何呈现此模板:

<table class="table" data-title=${table-name}>
<thead>
  <tr>
    <th>#</th>
    <table-head>
      <th> <table-hcell/> </th>
    </table-head>
  </tr>
</thead>
<tbody>
  <table-body>
    <tr data-oid=${table-rowid}>
      <td> <input type="checkbox"/> </td>
      <table-raw>
        <td> <table-rcell/> </td>
      </table-raw>
    </tr>
  </table-body>
</tbody>

1 个答案:

答案 0 :(得分:3)

假设这是我们想要呈现为表格的结构:

data Table = Table 
    {
      caption :: T.Text
    , rows :: [[Int]]
    }

一个简单的模板可能类似于

<body>
    <mytable>
    <table>
        <caption><mycaptiontext/></caption>
        <myrow>
        <tr>
            <mydata>
            <td><mydatavalue/></td>
            </mydata>
        </tr>
        </myrow>
    </table>
    </mytable>
</body>  

mytablemycaptiontextmyrowmydatamydatavalue是绑定到拼接的标记。特别是mytable将被绑定到顶层拼接。

要考虑三个级别:整个表,行和行内的数据。对于每个级别,我们将定义一个函数,该函数采用运行时操作并返回已编译的拼接。

对于“行数据”级别,运行时操作携带一行中的值列表:

dataSplice :: Monad m => RuntimeSplice m [Int] -> C.Splice m
dataSplice = C.manyWithSplices C.runChildren splicefuncs 
    where
    splicefuncs = do
        "mydatavalue"  ## (C.pureSplice . C.textSplice $ T.pack . show)

对于“行”级别,运行时操作包含完整的行列表:

rowSplice :: Monad m => RuntimeSplice m [[Int]] -> C.Splice m
rowSplice = C.manyWithSplices C.runChildren splicefuncs 
    where
    splicefuncs = do
        "mydata"  ## dataSplice

注意我们如何在定义中使用dataSplice

对于“整个表”级别,运行时操作带有Table

tableSplice :: Monad m => RuntimeSplice m Table -> Splice m
tableSplice = C.withSplices C.runChildren splicefuncs 
    where              
    splicefuncs = do  
        "mycaptiontext" ## (C.pureSplice . C.textSplice $ caption)
        "myrow"   ## (rowSplice .  liftM rows)    

请注意我们如何在此处使用liftM,将RuntimeSplice m Table转换为RuntimeSplice m [[Int]],以使该类型符合rowSplice期望的内容。

现在假设我们有一个生成表数据的运行时操作:

runtime :: Monad m => RuntimeSplice m Table
runtime = return $ Table "This is the caption" $
            [ [3, 5, 6], [8, 3, 7 ] ]  

(这个很简单。例如,更复杂的操作可以从数据库中获取数据。请记住,在Snap中,RuntimeSplices可以访问所有Snaplet机器。)

我们可以将tableSpliceruntime结合使用,并将结果注册为Heist配置中的顶级拼接,绑定到mytable标记。像这样:

let heistConfig = mempty { 
                     hcCompiledSplices = do
                           "mytable" ## (tableSplice runtime)
                           .... other top-level splices here ...
                    }

这应该有用。

可以在this tutorial中找到更多使用编译的Heist渲染嵌套结构的示例。