[英]Heist: How do I insert a dynamic list of sub-templates into a template?
I am writing a site for online surveys.我正在写一个在线调查网站。 I have a list of questions that all go on one html page and the list is of unknown length.
我有一个问题列表,其中一个 html 页面上的所有 go 并且该列表的长度未知。 Each question has the form stored in template
qu1.tpl
and the page is qu.tpl
.每个问题的表格都存储在模板
qu1.tpl
中,页面是qu.tpl
。 Now I want to:现在我想:
replace some names in qu1.tpl
for each question为每个问题替换
qu1.tpl
中的一些名称
replace some things in qu.tpl
once将
qu.tpl
中的一些东西替换一次
and stick all instantiations of qu1.tpl
into qu.tpl
并将 qu1.tpl 的所有实例化
qu1.tpl
到qu.tpl
Using what I learned in the tutorial, I tried to recursively replace a tag <qulist/>
with <apply template="qu1.tpl"><qulist/>
in qu.tpl
using localHeist
and bindString
but this cannot work because qu.tpl
is already rendered so the newly inserted apply tag doesn't resolve.使用我在教程中学到的知识,我尝试使用
localHeist
和bindString
在qu.tpl
中用<apply template="qu1.tpl"><qulist/>
递归替换标签<qulist/>
但这不起作用,因为qu.tpl
已呈现,因此新插入的应用标签无法解析。
what should I do instead?我应该怎么做?
(I guess this is a more general question. If you can think of other applications the answer applies to, please add text and tags for the search engines.) (我想这是一个更普遍的问题。如果您能想到答案适用的其他应用程序,请为搜索引擎添加文本和标签。)
In Heist, when you're doing something that involves calculations on dynamic data you usually will use a splice.在 Heist 中,当你做一些涉及动态数据计算的事情时,你通常会使用拼接。 Your first two points can be handled by binding splices.
您的前两点可以通过绑定拼接处理。 For the third point, I would start by creating a splice function that renders a particular question template.
对于第三点,我将首先创建一个呈现特定问题模板的拼接 function。 It would look something like this:
它看起来像这样:
questionSplice :: Monad m => Int -> Splice m
questionSplice n = do
splices <- setupSplicesForThisQuestion
mTemplate <- callTemplate (B.pack ("qu"++(show n))) splices
return $ fromMaybe [] mTemplate
Now you can create a splice for the list of survey questions:现在您可以为调查问题列表创建一个拼接:
surveyQuestions :: Monad m => Splice m
surveyQuestions = do
questions <- getSurveyQuestions
mapSplices questionSplice questions
Then you can bind this splice to a particular tag and use it anywhere in qu.tpl or any other template.然后,您可以将此拼接绑定到特定标签并在 qu.tpl 或任何其他模板中的任何位置使用它。
The important part here is the callTemplate function.这里重要的部分是 callTemplate function。 It is Heist's function for rendering templates from inside a TemplateMonad computation.
它是 Heist 的 function,用于从 TemplateMonad 计算内部渲染模板。 I don't think it is talked about much in the tutorials because it hasn't been a use case that people are usually concerned with, and it's easy to miss in the API docs.
我认为教程中没有太多讨论它,因为它不是人们通常关心的用例,而且在 API 文档中很容易错过。
thanks to mightybyte for helping me out with this on irc.感谢mightybyte在irc上帮助我解决这个问题。 after the 8 hours that i was banned from answering to myself, here is my variant of the same answer:
在我被禁止回答自己的 8 小时之后,这是我的相同答案的变体:
build a splice that reads template qu1.tpl, instantiates it (ie, fills in name and number of the question in the list), and returns it.构建一个读取模板 qu1.tpl 的拼接,将其实例化(即,在列表中填写问题的名称和编号),然后返回它。 the heist function callTemplate helps you with that.
抢劫 function callTemplate 可以帮助您。 (this splice is called splicex in the pseudocode below.)
(这个拼接在下面的伪代码中称为 splicex。)
write another splice that folds splicex so that you get a list of (instantiated) questions instead of a single one.编写另一个折叠 splicex 的拼接,以便获得(实例化的)问题列表而不是单个问题。 (function splice in the pseudocode.)
(伪代码中的函数拼接。)
use bindSplice instead of bindString.使用 bindSplice 而不是 bindString。
pseudocode (tested then modifed and ripped out of context) -伪代码(测试然后修改并脱离上下文) -
... -> 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"
btw, my sourceforge avatar is too weak to create new tags.顺便说一句,我的 sourceforge 头像太弱,无法创建新标签。 anybody care to tag this with 'heist'?
有人愿意用“抢劫”来标记这个吗?
links:链接:
http://snapframework.com/ http://snapframework.com/
#snapframework channel on the freenode IRC network. freenode IRC 网络上的#snapframework 频道。
http://snapframework.com/docs/tutorials/heist http://snapframework.com/docs/tutorials/heist
When I tried to figure out template loops, I stumbled multiple times across this question.当我试图找出模板循环时,我多次偶然发现这个问题。 Sadly, everything here is probably outdated, version 0.5 (or below) while version 0.6 (I guess) introduced runChildrenWith.
可悲的是,这里的一切都可能已经过时了,0.5 版(或更低版本)而 0.6 版(我猜)引入了 runChildrenWith。
A simple example for using runChildrenWith would be:使用 runChildrenWith 的一个简单示例是:
list_test_entries.tpl: list_test_entries.tpl:
<listTestEntries>
<dt><testEntry/></dt>
<dd>This is part of the repeated template</dd>
</listTestEntries>
Site.hs:网站.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)
See https://github.com/michaxm/heist-template-loop-demo for a running demo.有关运行演示,请参阅https://github.com/michaxm/heist-template-loop-demo 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.