[英]Heist: How do I insert a dynamic list of sub-templates into a template?
我正在写一个在线调查网站。 我有一个问题列表,其中一个 html 页面上的所有 go 并且该列表的长度未知。 每个问题的表格都存储在模板qu1.tpl
中,页面是qu.tpl
。 现在我想:
为每个问题替换qu1.tpl
中的一些名称
将qu.tpl
中的一些东西替换一次
并将 qu1.tpl 的所有实例化qu1.tpl
到qu.tpl
使用我在教程中学到的知识,我尝试使用localHeist
和bindString
在qu.tpl
中用<apply template="qu1.tpl"><qulist/>
递归替换标签<qulist/>
但这不起作用,因为qu.tpl
已呈现,因此新插入的应用标签无法解析。
我应该怎么做?
(我想这是一个更普遍的问题。如果您能想到答案适用的其他应用程序,请为搜索引擎添加文本和标签。)
在 Heist 中,当你做一些涉及动态数据计算的事情时,你通常会使用拼接。 您的前两点可以通过绑定拼接处理。 对于第三点,我将首先创建一个呈现特定问题模板的拼接 function。 它看起来像这样:
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 function。 它是 Heist 的 function,用于从 TemplateMonad 计算内部渲染模板。 我认为教程中没有太多讨论它,因为它不是人们通常关心的用例,而且在 API 文档中很容易错过。
感谢mightybyte在irc上帮助我解决这个问题。 在我被禁止回答自己的 8 小时之后,这是我的相同答案的变体:
构建一个读取模板 qu1.tpl 的拼接,将其实例化(即,在列表中填写问题的名称和编号),然后返回它。 抢劫 function callTemplate 可以帮助您。 (这个拼接在下面的伪代码中称为 splicex。)
编写另一个折叠 splicex 的拼接,以便获得(实例化的)问题列表而不是单个问题。 (伪代码中的函数拼接。)
使用 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 头像太弱,无法创建新标签。 有人愿意用“抢劫”来标记这个吗?
链接:
freenode IRC 网络上的#snapframework 频道。
当我试图找出模板循环时,我多次偶然发现这个问题。 可悲的是,这里的一切都可能已经过时了,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 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.