【问题标题】:How can I create a Yesod form where I can select from a dropdown list where the list is passed as an argument?如何创建一个 Yesod 表单,我可以从下拉列表中进行选择,该列表作为参数传递?
【发布时间】:2020-11-15 04:04:20
【问题描述】:

我想创建一个表单,在其中我传递一个 [a] 一个参数并返回一个 MForm Handler (FormResult a, Widget)

我曾尝试使用 selectFieldList 等函数来实现此功能,但未能找到解决方案。我无法在谷歌的任何地方找到答案。我发现了许多示例,其中下拉列表被用作较大表单中的单个字段,但没有一个下拉列表是整个表单本身。

编辑:

我已经设法制作了一个可以编译的表单。不幸的是,我无法判断它是否按我想要的方式工作,因为我无法让它渲染。

以下是我正在使用的关键函数(它们都可以编译):

mkCityStringM :: [PG.DbCity] -> [(T.Text, PG.DbCity)]
mkCityStringM xs = zip (map (T.pack . showDbCity) xs) xs

data ContainCity =
  ContainCity
    { getCity :: PG.DbCity
    }
  deriving (Show)

ambiguityForm :: [PG.DbCity] -> AForm Handler ContainCity
ambiguityForm cities = ContainCity 
   <$> areq (selectFieldList cityMap) "City" Nothing
  where
    cityMap :: [(T.Text, PG.DbCity)]
    cityMap = W.mkCityStringM cities

问题是当我尝试实际使用此表时遇到问题。这是对我来说很好用的代码:

locationForm :: Html -> MForm Handler (FormResult BasicLocation, Widget)
locationForm = renderDivs $ BasicLocation
  <$> areq textField "City:" Nothing
  <*> areq textField "Country:" (Just "United States")

postAmbiguityR :: [PG.DbCity] -> Handler Html
postAmbiguityR cs = do 
  (widget, enctype) <- generateFormPost locationForm
  defaultLayout $ do 
  [whamlet|
    <p>who cares
  |]  

另一方面,我有这个代码:

postAmbiguityR :: [PG.DbCity] -> Handler Html
postAmbiguityR cs = do 
  (widget, enctype) <- generateFormPost (ambiguityForm cs) --only difference
  defaultLayout $ do 
  [whamlet|
    <p> WHATEVER
  |]  

这引发了我这个错误:

    • Couldn't match expected type ‘blaze-markup-0.8.2.5:Text.Blaze.Internal.Markup
                                    -> MForm (HandlerFor Base) (FormResult a0, xml0)’
                  with actual type ‘AForm Handler ContainCity’
    • Possible cause: ‘ambiguityForm’ is applied to too many arguments
      In the first argument of ‘generateFormPost’, namely
        ‘(ambiguityForm cs)’
      In a stmt of a 'do' block:
        (widget, enctype) <- generateFormPost (ambiguityForm cs)
      In the expression:
        do (widget, enctype) <- generateFormPost (ambiguityForm cs)
           defaultLayout
             $ do (do (asWidgetT . toWidget)
                        ((blaze-markup-0.8.2.5:Text.Blaze.Internal.preEscapedText . T.pack)
                           "<html><header></header>
<form method="post" action="")
                      ....)
    |
132 |   (widget, enctype) <- generateFormPost (ambiguityForm cs)
    |                                          ^^^^^^^^^^^^^^^^

此错误消息对我来说没有意义。它说一个可能的原因是ambiguity form is applied to too many arguments,但似乎并非如此,因为该表单采用了 PG.DbCity 的列表,而这正是我提供的。

【问题讨论】:

  • 您能解释一下为什么包含单个 selectFieldList 字段的表单不适合您吗?是否存在字段标签和/或提交按钮的问题?你有一个MForm 的例子,它接近但有一些你想解决的具体问题?

标签: haskell yesod


【解决方案1】:

问题在于ambiguityFormAForm,但generateFormPost 需要MForm。要将其转换为适合渲染的MForm,您需要使用renderDivs,就像您在locationForm 示例中所做的那样。您可以或者ambiguityForm 的定义中执行此操作,这会将其类型/定义更改为如下所示:

ambiguityForm :: [PG.DbCity] -> Html -> MForm Handler (FormResult ContainCity, Widget)
ambiguityForm cities = renderDivs $ ContainCity ...

您可以保持ambiguityForm不变,并在使用站点添加renderDivs

postAmbiguityR :: [PG.DbCity] -> Handler Html
postAmbiguityR cs = do 
  (widget, enctype) <- generateFormPost (renderDivs (ambiguityForm cs))
  defaultLayout $ do 
  [whamlet|
    <p> WHATEVER
  |]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-29
    相关资源
    最近更新 更多