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

时间:2013-08-22 19:43:14

标签: 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开头的行。所以,我的问题是,如何在自定义字段中使用静态路由?如果有更多我应该提供的信息,请告诉我。感谢。

1 个答案:

答案 0 :(得分:3)

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

此解决方案之一就是通过将类型签名更改为以下内容,使jqueryDateTimeField特定于您的网站:

jqueryDateTimeField :: JqueryDaySettings -> Field Handler UTCTime

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

虽然这样可行,但更好的解决方案是使用YesodJquery的{​​{1}}函数获取日期时间选择器加载项的URL并将其添加为脚本。 urlJqueryUiDateTimePicker接受代表您网站的对象(本例中为urlJqueryUiDateTimePicker对象)并返回App - 您网站下的路线或基于文字的网址 - 指向javascript文件。您可以使用addScriptEitherEither (Route site) Text中将其添加为脚本。 然后,您可以更改jqueryDateTimeField的{​​{1}}实例以返回静态路由。

因此,请将App替换为:

YesodJquery

并更改addScript $ StaticR js_jquery_ui_timepicker_addon_js的{​​{1}}实例中的app <- getYesod -- This gets your App object addScriptEither (urlJqueryUiDateTimePicker app) 方法,以返回您要使用的路线:

urlJqueryUiDateTimePicker

1 在原始类型签名中,处理程序由App表示,其中YesodJquery满足约束instance YesodJquery App where urlJqueryUiDateTimePicker _ = Left $ StaticR js_jquery_ui_timepicker_addon_js HandlerT site IOsite要求RenderMessage site FormMessage必须知道如何从FormMessage数据类型生成消息。 YesodJquery site要求站点必须能够访问jQuery,jQuery UI和jQuery UI日期时间选择器加载项(see here)的静态文件。