【问题标题】:How to build a pre-selected option for a selectField in Yesod?如何在 Yesod 中为 selectField 构建预选选项?
【发布时间】:2018-09-17 20:54:27
【问题描述】:

(This was asked before but it has no answers).

我在数据库中有一个国家/地区列表:

share [mkPersist sqlSettings] [persistLowerCase|
Country
  name Text
  UniqueCountryName name
  deriving Show
|]

我可以显示一个表格来选择其中一个:

countries = do
  rows <- runDB $ selectList [] [Asc CountryName]
  optionsPairs $ map (\ r -> (countryName $ entityVal r, entityKey r)) rows

surveyForm :: Html -> MForm Handler (FormResult SurveyAnswerSet, Widget)
surveyForm extra = do
  (countryR, countryV) <- mreq (selectField countries) "" Nothing

我知道我应该将最后一行中的Nothing 替换为所需的默认值,但我仍然不知道该怎么做。查看mreqoptionsPairs 签名,我的想法是,在这种情况下,我应该提供带有默认国家/地区的Maybe Option,但我的尝试引发了很多类型错误,以至于我可能离正确答案还很远。

Yesod 书中有一个示例,使用似乎比我试图实现的更简单,所以我不知道如何推断它。

顺便说一下,我是从数据库中获取默认国家/地区的,所以我不需要硬编码其内部 ID:

defaultCountry = do
  row <- runDB $ getBy $ UniqueCountryName $ countryName "United States"
  (countryName $ entityVal row, entityKey row)

当我将它作为参数传递给 mreq 时,我收到以下错误:

无法将类型“(,) Text”与“HandlerFor site”匹配 预期类型:HandlerFor 站点(关键记录) 实际类型:(文本,关键记录)

这是defaultContry 函数 ((countryName $ entityVal row, entityKey row)) 的最后一行。我知道我应该从这对中取出 Key record 并将其返回到 HandlerFor site 但同时我也得到:

无法匹配预期类型“可能(关键国家)” 实际类型为“HandlerFor site0 (Key record0)”

(countryR, countryV) &lt;- mreq (selectField countries) "" defaultCountry 行中。我将此解释为“您传递给我一个HandlerFor site0 (Key record0),但我只接受Maybe (Key Country),这似乎与第一个错误相冲突......

(countryName $ entityVal row, entityKey row) 行我还看到:

无法匹配预期类型“实体国家/地区” 实际类型为“可能(实体国家)”

row 参数中。我知道我应该从Maybe 中提取Entity Country,但是如果我模式匹配并仅传递Entity Country(即:Just (Entity countryId country) -&gt; (countryName $ entityVal (Entity countryId country), entityKey (Entity countryId country)),我仍然会收到第一个错误。

提前致谢。

【问题讨论】:

  • mreq 中的默认值不是 OptionPair 的默认值,而是填充 countryR (或 countryV ,它曾经包含该值)的默认值。在您的情况下,它可能是 Text 或 CountryKey。
  • 这里的类型有点混乱——你认为你可以注释defaultCountrycountries吗?否则,我看不出你为什么不做(name, key) &lt;- defaultCountry; (countryR, countryV) &lt;- mreq (selectField countries) "" (Just key)
  • 谢谢大家,我用 GHC 错误更新了我的问题。它们包括预期和提供的类型。我试图跟随他们,但我迷路了,因为他们中的两个似乎发生了冲突。

标签: haskell yesod yesod-forms


【解决方案1】:

好的,这看起来像一些类型错误。第一个

无法将类型“(,) Text”与“HandlerFor site”匹配预期类型:HandlerFor site(关键记录)实际类型:(文本,关键记录)

来自于未在 do 表示法中使用 return 将值提升到 monad:

defaultCountry :: HandlerFor site (Text, Key record)
defaultCountry = do
  row <- runDB $ getBy $ UniqueCountryName $ countryName "United States"
  return (countryName $ entityVal row, entityKey row)

row 的错误

无法将预期类型“实体国家”与实际类型“可能(实体国家)”匹配

因为它是Maybe,所以让我们更正一下

defaultCountry :: HandlerFor site (Text, Key record)
defaultCountry = do
  Just row <- runDB $ getBy $ UniqueCountryName $ countryName "United States"
  return (countryName $ entityVal row, entityKey row)

既然defaultCountry 是一个很好的monad,你应该可以在你的其他代码中使用它。但要小心第三个错误

无法将预期类型“Maybe (Key Country)”与实际类型“HandlerFor site0 (Key record0)”匹配

您需要从 HandlerFor monad 中解包值,并将其重新包装在 Maybe

surveyForm :: Html -> MForm Handler (FormResult SurveyAnswerSet, Widget)
surveyForm extra = do
  (defaultName, defaultKey) <- defaultCountry -- (defaultName, defaultKey) :: (Text, Key record)
  (countryR, countryV) <- mreq (selectField countries) "" (Just defaultKey)

【讨论】:

  • 我仍然看到几个错误,但是新的!如果我只将更改应用到 defaultCountry 函数,我会得到 Couldn't match type ‘record’ with ‘Country’ ‘record’ is a rigid type variable bound by the type signature for: defaultCountry :: forall site record. HandlerFor site (Text, Key record) at app/Main.hs:54:1-52 Expected type: HandlerFor site (Text, Key record) Actual type: HandlerFor site (Text, Key Country)
  • 然后只需将类型声明中的record 替换为Country
  • 哦,对了 ? 但现在错误更奇怪了Couldn't match type ‘BaseBackend (YesodPersistBackend site)’ with ‘SqlBackend’ arising from a use of ‘getBy’。我减少了对这个gist.github.com/tssm/3a503fb60cde023d05a33cf2248e7d40 的尝试(我还有其他几个表单字段,它一直有效,直到我尝试预先选择一个选项)
  • 从您共享的代码看来,您应该在类型签名中放入 App 而不是 site
  • 这减少了错误,足以让我弄清楚接下来的步骤:1.从数据库中获取默认国家/地区,我应该只使用UniqueCountryName而不是UniqueCountryName $ countryName)和2.defaultContry必须在SurveyForm 中解除才能获得defaultKey。非常感谢您的耐心等待!
猜你喜欢
  • 2012-03-02
  • 2013-01-04
  • 2012-12-20
  • 2021-03-10
  • 2012-06-19
  • 1970-01-01
  • 2016-05-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多