【问题标题】:Heist: How do I insert a dynamic list of sub-templates into a template?Heist:如何将子模板的动态列表插入到模板中?
【发布时间】:2011-10-10 21:57:56
【问题描述】:

我正在编写一个用于在线调查的网站。我有一个问题列表,所有问题都在一个 html 页面上,并且列表长度未知。每个问题的表格都存储在模板qu1.tpl 中,页面为qu.tpl。现在我想:

  1. 为每个问题替换qu1.tpl 中的一些名称

  2. qu.tpl中的一些东西替换一次

  3. 并将qu1.tpl 的所有实例化粘贴到qu.tpl

使用我在教程中学到的知识,我尝试使用 localHeistbindString 递归地将标签 <qulist/> 替换为 <apply template="qu1.tpl"><qulist/> 中的 localHeistbindString 但这不起作用,因为 qu.tpl 已经呈现,所以新插入的应用标签无法解析。

我应该怎么做?

(我想这是一个更笼统的问题。如果您能想到答案适用于其他应用程序,请为搜索引擎添加文本和标签。)

【问题讨论】:

  • 似乎这里的一般问题可能是“子模板”,而mightybyte给出的答案是当我们有递归模板时(当我们想编写拼接来呈现递归类型时)最好的方法?递归模板已经让我绊倒了几次,所以如果 callTemplate 可能是缺少的链接,我很高兴。

标签: web-applications haskell haskell-snap-framework heist


【解决方案1】:

在 Heist 中,当您进行涉及动态数据计算的事情时,您通常会使用拼接。您的前两点可以通过绑定拼接处理。对于第三点,我将首先创建一个呈现特定问题模板的拼接函数。它看起来像这样:

questionSplice :: Monad m => Int -> Splice m
questionSplice n = do
  splices <- setupSplicesForThisQuestion
  mTemplate <- callTemplate (B.pack ("qu"++(show n))) splices
  return $ fromMaybe [] mTemplate

现在您可以为调查问题列表创建拼接:

surveyQuestions :: Monad m => Splice m
surveyQuestions = do
  questions <- getSurveyQuestions
  mapSplices questionSplice questions

然后您可以将此拼接绑定到特定标签并在 qu.tpl 或任何其他模板中的任何位置使用它。

这里的重要部分是 callTemplate 函数。这是 Heist 的函数,用于从 TemplateMonad 计算中渲染模板。我认为教程中没有过多讨论它,因为它不是人们通常关心的用例,而且很容易在 API 文档中遗漏。

【讨论】:

    【解决方案2】:

    感谢mightybyte 在irc 上帮助我解决这个问题。在我被禁止回答自己的 8 小时之后,这是我的相同答案的变体:

    1. 构建一个读取模板 qu1.tpl 的拼接,将其实例化(即,在列表中填写问题的名称和编号)并返回它。抢劫功能 callTemplate 可以帮助您。 (这个拼接在下面的伪代码中称为 splicex。)

    2. 编写另一个折叠 splicex 的 splice,以便获得(实例化的)问题列表,而不是单个问题。 (伪代码中的函数拼接。)

    3. 使用 bindSplice 代替 bindString。

    伪代码(经过测试然后修改并脱离上下文)-

     ... -> let
              splice :: Monad m => Splice m
              splice = foldM (\ ts (s, i) ->
                                 liftM ((++) ts) $ splicex (quName, quNumber))
                             []
                             (zip questionName [0..])
    
              splicex :: Monad m => (String, Int) -> Splice m
              splicex (quName, quNumber) =
                  do
                    mt <- callTemplate "qu1"
                            [ ("question-name", Data.Text.pack quName)
                            , ("question-number", Data.Text.pack $ show quNumber)
                            ]
    
                    case mt of
                      Nothing -> error "splice rendering failed."
                      Just (t :: Template) -> return t
             in
               -- fill in the list of (instatiated) questions
               heistLocal (bindSplice "qulist" splice) $
               -- before that, instantiate the overall page
               instantiatePage $
               render "qu"
    

    顺便说一句,我的 sourceforge 头像太弱,无法创建新标签。有人愿意用“抢劫”来标记这个吗?

    链接:

    http://snapframework.com/

    freenode IRC 网络上的#snapframework 频道。

    http://snapframework.com/docs/tutorials/heist

    【讨论】:

      【解决方案3】:

      当我试图找出模板循环时,我多次偶然发现这个问题。可悲的是,这里的一切都可能已经过时了,0.5 版(或更低版本)而 0.6 版(我猜)引入了 runChildrenWith。

      使用 runChildrenWith 的一个简单示例是:

      list_test_entries.tpl:

      <listTestEntries>
        <dt><testEntry/></dt>
        <dd>This is part of the repeated template</dd>
      </listTestEntries>
      

      网站.hs:

      listTestEntriesHandler :: Handler App App  ()
      listTestEntriesHandler = do
          results <- getData 
          renderWithSplices "list_test_entries"
              ("listTestEntries" ## listTestEntriesSplice results)
      
      getData :: Handler App App [String]
      getData = return ["1", "2", "3"]
      
      listTestEntriesSplice  :: [String] -> I.Splice AppHandler
      listTestEntriesSplice = I.mapSplices (I.runChildrenWith . listTestEntrySplice)
      
      listTestEntrySplice :: Monad m => String -> Splices (HeistT n m Template)
      listTestEntrySplice dataEntry = do
        "testEntry" ## I.textSplice (T.pack $ "data: " ++ dataEntry)
      

      请参阅https://github.com/michaxm/heist-template-loop-demo 以获取正在运行的演示。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-29
        • 2011-02-01
        • 2020-06-05
        • 1970-01-01
        相关资源
        最近更新 更多