haskell - Yesod 中自定义字段中的静态路由

标签 haskell yesod

我正在开发一个自定义字段,用于在 Yesod 中选择日期时间(存储为 UTCTime)。它使用 Trent Richardson's timepicker 。我实际上已经可以使用它了。唯一的问题是我在处理程序中而不是在自定义字段中拥有指向 javascript 文件的静态路由。当我将其移至自定义字段时,出现错误。部分代码(大部分复制自 yesod.form.fields)如下:

jqueryDateTimeField :: (RenderMessage site FormMessage, YesodJquery site) => JqueryDaySettings -> Field (HandlerT site IO) UTCTime
jqueryDateTimeField jds = Field
{
    fieldParse = parseHelper $ maybe (Left MsgInvalidDay) Right . readUTC . unpack
  , fieldView = \theId name attrs val isReq -> do
        toWidget [shamlet|
$newline never
<input id="#{theId}" name="#{name}" *{attrs} type="text" :isReq:required="" value="#{showVal val}">
|]
        addScript' urlJqueryJs
        addScript' urlJqueryUiJs
        addScript $ StaticR js_jquery_ui_timepicker_addon_js -- Bad line here
        addStylesheet' urlJqueryUiCss    --error seems to occurs on the line below
        toWidget [julius|
$(function(){
var i = document.getElementById("#{rawJS theId}");
$(i).datetimepicker({
    dateFormat:'yy-mm-dd',
    changeMonth:#{jsBool $ jdsChangeMonth jds},
    changeYear:#{jsBool $ jdsChangeYear jds},
    numberOfMonths:#{rawJS $ mos $ jdsNumberOfMonths jds},
    yearRange:#{toJSON $ jdsYearRange jds}
});
});
|]
  , fieldEnctype = UrlEncoded
}

显示 addScript $ StaticR js_jquery_ui_timepicker_addon_js 的行是导致问题的原因。我知道这一点是因为当我将该行放入调用该字段的处理程序中时,它会起作用。我收到一条错误消息

DateTime.hs:73:13:
Could not deduce (site ~ App)
from the context (RenderMessage site FormMessage, YesodJquery site)
  bound by the type signature for
             jqueryDateTimeField :: (RenderMessage site FormMessage,
                                     YesodJquery site) =>
                                    JqueryDaySettings -> Field (HandlerT site IO) UTCTime

事情还在继续,但令我困扰的是错误似乎发生在错误的行上。第 73 行是以 toWidget 开头的行。所以,我的问题是,如何在自定义字段中使用静态路由?如果我需要提供更多信息,请告诉我。谢谢。

最佳答案

这失败了,因为你的 jqueryDateTimeField是通用的,即它可以与任何满足给定约束1的 Yesod 网站一起使用,但您的 StaticR指专门为您的站点定义的路由构造函数,由 App 表示数据类型(在 Foundation.hs 中定义)。错误Could not deduce (site ~ App)意味着您使用 StaticR ,编译器期望 siteApp 相同总是如此,但您的其他约束并不能为编译器确认这一点。

解决这个问题的一个方法就是简单地制作 jqueryDateTimeField特定于您的站点,将类型签名更改为:

jqueryDateTimeField :: JqueryDaySettings -> Field Handler UTCTime

请注意HandlerHandlerT App IO 的类型同义词— 您网站的处理程序。

虽然这可行,但更好的解决方案是使用 YesodJqueryurlJqueryUiDateTimePicker函数来获取日期时间选择器插件的 URL 并将其添加为脚本。 urlJqueryUiDateTimePicker接受代表您站点的对象(在本例中为 App 对象)并返回 Either (Route site) Text — 您网站下的路由或基于文本的 URL — 指向 javascript 文件。您可以将其添加为 jqueryDateTimeField 中的脚本使用 addScriptEither 。 然后,您可以更改 AppYesodJquery实例返回您的静态路由。

所以,替换 addScript $ StaticR js_jquery_ui_timepicker_addon_js与:

app <- getYesod   -- This gets your App object
addScriptEither (urlJqueryUiDateTimePicker app)

并更改urlJqueryUiDateTimePicker App中的方法的YesodJquery实例返回您要使用的路线:

instance YesodJquery App where
    urlJqueryUiDateTimePicker _ = Left $ StaticR js_jquery_ui_timepicker_addon_js

1 在原始类型签名中,处理程序由 HandlerT site IO 表示。哪里site满足约束RenderMessage site FormMessageYesodJquery siteRenderMessage site FormMessage要求site必须知道如何从 FormMessage 生成消息数据类型。 YesodJquery site要求网站必须能够访问 jQuery、jQuery UI 和 jQuery UI 日期时间选择器插件 ( see here ) 的静态文件。

关于haskell - Yesod 中自定义字段中的静态路由,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18389499/

相关文章:

Haskell - 定义函数

haskell - 理解 Yesod Persistent TH 生成的代码

haskell - 为 Haskell 安装 Yesod 时出现问题

haskell - 这个 YesodAuth 实例有什么问题?

haskell - 开始使用 Yesod

haskell - Haskell 标准库类型类的替代实现

scala - 使类型签名独立于特定的 monad 转换器堆栈 (Scala)

haskell - 自动导出PathPiece

haskell - ccall 和 capi FFI 调用约定之间的差异

Haskell:改进我的尾递归斐波那契实现