我正在努力将一个站点从PHP移植到Snap w/Heist.我已经将一些更简单的形式移植到成功使用Digestive Functors,但现在我必须做一些需要使用子表单的棘手的形式.
此应用程序管理为零售商店生产传单,因此需要完成的任务之一是添加广告尺寸并在打印的传单上定义其物理尺寸.尺寸将根据页面类型(可由传单所有者配置)及其方向(只能由管理员控制)而有所不同.

这种形式保证至少有3个单元格,最有可能有9个单元格(如上图所示的PHP版本),但理论上可以有无限数量.
这是我到目前为止维度子表单的内容:
data AdDimensions = AdDimensions
    { sizeId :: Int64
    , layoutId :: Int64
    , dimensions :: Maybe String
    }
adDimensionsForm :: Monad m => AdDimensions -> Form Text m AdDimensions
adDimensionsForm d = AdDimensions
    <$> "size_id" .: stringRead "Must be a number" (Just $ sizeId d)
    <*> "layout_id" .: stringRead "Must be a number" (Just $ layoutId d)
    <*> "dimensions" .: opionalString (dimensions d)
Run Code Online (Sandbox Code Playgroud)
表单定义感觉不太正确(也许我在这里完全错误的想法?).  AdDimensions.dimensions应该是a Maybe String,因为在运行查询时从数据库返回时它将为null,以获取新广告大小的size_id/layout_id的所有可能组合的列表,但是从类似查询中它不会为null将在创建编辑表单时运行.字段本身是必需的(在数据库中ad_dimensions.dimensions设置not null). …
我正在尝试使用Happstack,Heist和Web路由编写应用程序服务器,但是我很难弄清楚如何让拼接访问不是源自我的应用程序的monad堆栈的值.
出现这种情况有两种情况:
请考虑以下尝试提供以下URL的示例程序:
由于参数显示在URL路径而不是查询字符串中,因此它将通过Web路由而不是来自ServerPartT monad提取.但是,从那里开始,没有明确的方法将参数放在拼接可以看到的位置,因为它们只能访问应用程序monad.
将ReaderT粘贴在monad堆栈上的明显解决方案有两个问题:
从Snap文档中窥视,看起来Snap通过有效地将它们复制到查询字符串中来处理URL路径中的参数,从而回避问题.但这不是Happstack和网络路由的选择,此外,有两种不同的方式让URL指定相同的值会让我觉得安全性是一个坏主意.
那么,是否有一种"正确"的方式将非应用程序monad请求数据公开给拼接,或者我是否需要放弃Heist并使用像Blaze-HTML这样的东西而不是问题?我觉得我错过了一些明显的东西,但无法弄清楚它可能是什么.
示例代码:
{-# LANGUAGE TemplateHaskell #-}
import Prelude hiding ((.))
import Control.Category ((.))
import Happstack.Server (Response, ServerPartT, nullConf, ok, simpleHTTP)
import Happstack.Server.Heist (render)
import Text.Boomerang.TH (derivePrinterParsers)
import Text.Templating.Heist (Splice, bindSplices, emptyTemplateState, getParamNode)
import Text.Templating.Heist.TemplateDirectory (TemplateDirectory, newTemplateDirectory')
import Web.Routes (RouteT, Site, runRouteT)
import Web.Routes.Boomerang (Router, anyString, boomerangSite, int, lit, (<>), (</>))
import Web.Routes.Happstack (implSite)
import qualified Data.ByteString.Char8 as C …Run Code Online (Sandbox Code Playgroud) 我正在为在线调查写一个网站.我有一个问题列表,所有问题都在一个html页面上进行,列表的长度未知.每个问题都有表格存储在模板中qu1.tpl,页面是qu.tpl.现在我想:
qu1.tpl为每个问题替换一些名称
qu.tpl一次性更换一些东西
并坚持的所有实例qu1.tpl进qu.tpl
用我在教程中了解到,我试图递归更换标签<qulist/>与<apply template="qu1.tpl"><qulist/>在qu.tpl使用localHeist和bindString但这不能工作,因为qu.tpl这样的新插入的应用标签不能解决已经呈现.
我该怎么做呢?
(我想这是一个更普遍的问题.如果您能想到答案适用的其他应用程序,请为搜索引擎添加文本和标签.)
我最近升级了我正在使用的Heist版本.这主要是一个随意的决定,我仍然看到该行动的后果,主要是更令人愉快的代码结构.
但是,我非常依赖模板中的"apply"标签来引入样板组件,例如我的站点标题和菜单.对我来说,典型的模板如下所示:
<html>
<head>
    <title> <PageTitle /> </title>
    <link rel="stylesheet" type="text/css" href="/styles/style.css" />
    <link rel="alternate" type="application/rss+xml" title="${PageTitle} Feed" href="http://www.savannidgerinel.com/rss" />
</head>
<body class="center">
<apply template="header" />
<div id="content">
<h1><PageTitle /></h1>
<ul>
<PageMetadata />
</ul>
<PageContent />
</div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
而且,我现在正在加载这样的模板:
setup_heist template_dir = do
    templates <- Heist.loadTemplates template_dir
    hs <- Heist.initHeist (Heist.HeistConfig [] [] [] [] templates)
    return hs
Run Code Online (Sandbox Code Playgroud)
这与我以前加载模板的方式(仍然使用该loadTemplates函数)没有太大的不同,但它是设置我不习惯的Heist状态的另一种方式.
但是,现在没有apply任何标签有任何影响.我的"包含"模板永远不会加载,在生成的HTML中我看到这个:
<apply template='header'></apply>
Run Code Online (Sandbox Code Playgroud) 我想我前段时间确实问了一个类似的问题,但由于API不稳定而没有回答.所以我在等待0.13经过.我不确定提出类似问题是否正确......?
什么是替代解释runChildrenWith(Text),并mapSplices在编译的接头世界吗?(这种组合似乎是最常见的)如果可能,我真的很感谢一些代码示例.
如果我理解正确,我们将所有应用程序拼接汇集在一起,然后将它们添加到heistInit.有人能说明怎么做吗?
splice绑定标记在整个应用程序中必须是唯一的吗?
是否有完整的快照项目utilising新API和编译的拼接,以便我可以阅读和看到学习?
谢谢.
- 更新 -
下面很好的答案.但不幸的是,有些部分(带镜头的部分)让我更加困惑.如果我理解正确,这是拼接字符串的简单方法:
mySplice = "testSplice" ## testSplice
  where testSplice = return $ C.yieldRuntimeText $ do
          return "text to be spliced"
Run Code Online (Sandbox Code Playgroud)
如果我需要多次运行拼接字符串,比如在5个表格中,我会这样做:
mySplices = C.manyWithSplices C.runChildren mySplice
Run Code Online (Sandbox Code Playgroud)
它是否正确?
我试图在抢劫配置中添加拼接时遇到一堆错误.
addConfig h $ mempty
 {
   hcCompiledSplices = "mySplice" ## mySplice -- or mySplices
 }
Run Code Online (Sandbox Code Playgroud)
我哪里错了?抱歉很慢.
所有我真正需要的(只是现在,所以我能理解)是拼接和显示我从数据库收到的简单字符串.
- 更新2 -
感谢极端有用的丹尼尔回答我终于可以得到一些有用的东西了.
到目前为止,我得到了两种代码变体.
第一个,感谢Daniel
stringSplice :: Monad n => C.Splice n
stringSplice = C.manyWithSplices C.runChildren splicefuncs (return ["aa","bb","cc"]) …Run Code Online (Sandbox Code Playgroud)