1

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

这里描述了原始问题:渲染表格

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

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

我可以毫无问题地使用解释的变量来做到这一点。tableRawS 的解释示例由文档参数化,但映射到 [labels]。我无法在编译的变体中实现这一点。我需要 tableRaw 函数中存在的文档和标签列表,以便我可以将不同的单元格拼接从文档中绑定出来。这是真正的痛苦。我不知道该怎么做。无论我做什么,我最终都会在文档上映射 tableRaw,而不是在标签列表上映射。

基本上。我从具有上述文档结构的数据库中获取 [document],并从数据库中获取标签,其中

 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>

4

1 回答 1

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>  

其中mytablemycaptiontextmyrow和是将绑定到接头的标签mydata。特别是将绑定到顶级拼接。mydatavaluemytable

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

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

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在这里如何使用,将 aRuntimeSplice m Table转换为 aRuntimeSplice 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机器。)

我们可以将结果tableSpliceruntimeHeist 配置中的顶级拼接组合并注册为绑定到mytable标签的顶级拼接。像这样:

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

这应该有效。

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

于 2013-11-02T16:54:37.527 回答