2013-08-22 31 views
1

我正在處理用於在Yesod中選擇日期時間的自定義字段(存儲爲UTCTime)。它使用Trent Richardson's timepicker。我其實已經開始工作了。唯一的問題是,我有一個處理程序而不是自定義字段中的JavaScript文件的靜態路由。當我將它移動到自定義字段時,出現錯誤。代碼(從yesod.form.fields主要是複製)的一部分低於:Yesod中的自定義字段中的靜態路由

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開頭的行。所以,我的問題是,如何在自定義字段中使用靜態路由?如果有更多我應該提供的信息,請告訴我。謝謝。

回答

3

失敗的原因是你的jqueryDateTimeField是通用的,也就是說,它會與滿足給定約束任何耶索德現場工作,但你的StaticR是指專門爲您的網站定義的路由構造,這是由代表數據類型爲App(在Foundation.hs中定義)。錯誤Could not deduce (site ~ App)意味着給定使用StaticR,編譯器期望site始終與App相同,但是其他約束無法爲編譯器確認。

一種解決方法很簡單,就是讓jqueryDateTimeField具體到您的網站通過更改類型簽名:

jqueryDateTimeField :: JqueryDaySettings -> Field Handler UTCTime 

注意HandlerHandlerT App IO一種代名詞 - 處理程序爲您的網站。

儘管這樣可行,但更好的解決方案是使用YesodJqueryurlJqueryUiDateTimePicker函數獲取日期時間選取器加載項的URL並將其添加爲腳本。 urlJqueryUiDateTimePicker接受表示您網站的對象(本例中爲App對象),並返回Either (Route site) Text - 指向您的網站或基於文本的網址 - 指向JavaScript文件。您可以使用addScriptEither將它作爲jqueryDateTimeField中的腳本添加。 然後,您可以更改AppYesodJquery實例以返回您的靜態路由。

所以,更換addScript $ StaticR js_jquery_ui_timepicker_addon_js有:

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

而改變AppYesodJquery實例urlJqueryUiDateTimePicker方法返回要使用的路線:

instance YesodJquery App where 
    urlJqueryUiDateTimePicker _ = Left $ StaticR js_jquery_ui_timepicker_addon_js 

在原始類型簽名中,處理程序由表示HandlerT site IO其中site滿足約束RenderMessage site FormMessageYesodJquery siteRenderMessage site FormMessage要求site必須知道如何從FormMessage數據類型生成消息。 YesodJquery site要求網站必須有權訪問jQuery,jQuery UI和jQuery UI日期時間選擇器插件(see here)的靜態文件。