2

我正在研究一个自定义字段,用于在 Yesod 中选择日期时间(存储为 UTCTime)。它使用Trent Richardson 的 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。所以,我的问题是,如何在自定义字段中使用静态路由?如果我应该提供更多信息,请告诉我。谢谢。

4

1 回答 1

4

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

解决此问题的一种方法是jqueryDateTimeField通过将类型签名更改为特定于您的站点:

jqueryDateTimeField :: JqueryDaySettings -> Field Handler UTCTime

请注意,这是您站点的处理程序Handler的类型同义词。HandlerT App IO

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

所以,替换addScript $ StaticR js_jquery_ui_timepicker_addon_js为:

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

并更改's实例中的urlJqueryUiDateTimePicker方法以返回您要使用的路由:AppYesodJquery

instance YesodJquery App where
    urlJqueryUiDateTimePicker _ = Left $ StaticR js_jquery_ui_timepicker_addon_js

1 在原始类型签名中,处理程序由HandlerT site IOwheresite满足约束RenderMessage site FormMessageYesodJquery site. RenderMessage site FormMessage要求site必须知道如何从FormMessage数据类型生成消息。 YesodJquery site要求站点必须能够访问 jQuery、jQuery UI 和 jQuery UI 日期时间选择器附加组件的静态文件(请参阅此处)。

于 2013-08-24T05:04:57.207 回答