我正在开发一个自定义字段,用于在 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
,编译器期望 site
与 App
相同总是如此,但您的其他约束并不能为编译器确认这一点。
解决这个问题的一个方法就是简单地制作 jqueryDateTimeField
特定于您的站点,将类型签名更改为:
jqueryDateTimeField :: JqueryDaySettings -> Field Handler UTCTime
请注意Handler
是 HandlerT App IO
的类型同义词— 您网站的处理程序。
虽然这可行,但更好的解决方案是使用 YesodJquery
的urlJqueryUiDateTimePicker
函数来获取日期时间选择器插件的 URL 并将其添加为脚本。 urlJqueryUiDateTimePicker
接受代表您站点的对象(在本例中为 App
对象)并返回 Either (Route site) Text
— 您网站下的路由或基于文本的 URL — 指向 javascript 文件。您可以将其添加为 jqueryDateTimeField
中的脚本使用 addScriptEither
。
然后,您可以更改 App
的YesodJquery
实例返回您的静态路由。
所以,替换 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 FormMessage
和YesodJquery site
。
RenderMessage site FormMessage
要求site
必须知道如何从 FormMessage
生成消息数据类型。
YesodJquery site
要求网站必须能够访问 jQuery、jQuery UI 和 jQuery UI 日期时间选择器插件 ( see here ) 的静态文件。
关于haskell - Yesod 中自定义字段中的静态路由,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18389499/