Forms 使用yesod表单发布/重定向/获取后保留不正确的用户输入
最近我偶然发现了以下问题:Forms 使用yesod表单发布/重定向/获取后保留不正确的用户输入,forms,haskell,yesod,post-redirect-get,Forms,Haskell,Yesod,Post Redirect Get,最近我偶然发现了以下问题: 用我想要的 显示应用程序窗体,并让用户将其数据发布到特殊处理程序 在FormFailure上,将浏览器重定向到上一页 打印错误消息 。。。并重新显示已用不正确的用户提供的数据填写的表单 就我而言,这就是一切 虽然这些要点需要一个简单而直接的实现,但我发现不可能实现这一点 yesod表单包会自动处理这个问题,但不允许像我希望的那样在表单解析和错误处理之间进行任何重定向 对迈克尔·斯诺曼回答的回应 您建议我序列化提交的数据,并在重定向后以某种方式将其注入表单。这将引出更详
用我想要的
FormFailure
上,将浏览器重定向到上一页yesod表单包会自动处理这个问题,但不允许像我希望的那样在表单解析和错误处理之间进行任何重定向 对迈克尔·斯诺曼回答的回应 您建议我序列化提交的数据,并在重定向后以某种方式将其注入表单。这将引出更详细的问题:
::GHandler s m RequestBodyContents
,但哪些是相关信息(字段的名称
是自动生成的)字段
的类型相同,因此无法重新插入可能无法正确解析的用户提供的数据
示例:用户在intField
中键入“A”。现在,我希望在重定向后能够在同一字段中显示“A”,但API不允许我这样做我应该如何处理这个问题?我个人认为返回带有POST请求的已填写表单是可以接受的,这正是yesod表单API优化的目的。如果您还想在表单提交失败时强制重定向,则需要序列化提交的数据并将其存储在某个位置,例如:
这是一个老问题,但我今天需要这个,所以不妨将它发布给遇到相同问题的其他人 基本上,正如Michael所建议的,我们可以将数据序列化到会话中。做这件事很棘手,而且把它做成一个表格更为棘手。我不得不从
Yesod.Form.Functions
中删除postEnv
和postHelper
,因为它们不是导出的,但需要这样做
然后,可以在重定向之前在处理程序中使用setLastInvalidPost
,然后在目标处理程序中使用generateFormFromLastPost
请注意,最好使用Data.Serialize
之类的方法进行序列化;然而,Show
/Read
实例对于我的需求来说已经足够好了(而且更简单)
这是好东西。如果需要完整的工作代码段
--根据会话中的最后一个post数据创建表单(如果存在),否则创建空白表单。
generateFormFromLastPost::(RenderMessage(HandlerSite m)FormMessage,MonadHandler m)=>
(标记->MForm m(FormResult a,xml))->m(xml,Enctype)
generateFormFromLastPost表单=do
环境生成表单
只是->第一个snd postHelper表单环境
lastInvalidPostSessionKey::Text
lastInvalidPostSessionKey=“lastInvalidPost”
--设置从postEnv检索的post数据,忽略FileEnv。
setLastInvalidPost::MonadHandler m=>Maybe(Env,FileEnv)->m()
setLastInvalidPost Nothing=返回()
setLastInvalidPost(Just(env,))=会话设置器lastInvalidPostSessionKey env
--检索要传递给postHelper的上一个post数据。
getLastInvalidPost::MonadHandler m=>m(可能是(Env,FileEnv))
getLastInvalidPost=do
一无所获
Just env->Just(env,Map.fromList[])
sessionSetter::(MonadHandler m,Show a)=>Text->a->m()
sessionSetter键=设置会话键。打包。显示
sessionGetter::(MonadHandler m,读b)=>Text->m(可能是b)
sessionGetter键=do
我会尝试用javascript和Cookie(会话-)来解决这个问题,Cookie实际上是一个好主意,但是我想避免使用javascript。我确信这个问题存在解决方案。谢谢你的回复。我会用你的方法,但它不能解决我所有的问题。我编辑了我的问题,提供了我实际需要的更详细的信息。
aopt :: Field sub master a -> FieldSettings master -> Maybe (Maybe a) -> AForm sub master (Maybe a)
-- Create a form from last post data in the session if exists, otherwise create a blank form.
generateFormFromLastPost :: (RenderMessage (HandlerSite m) FormMessage, MonadHandler m) =>
(Markup -> MForm m (FormResult a, xml)) -> m (xml, Enctype)
generateFormFromLastPost form = do
env <- getLastInvalidPost
case env of
Nothing -> generateFormPost form
Just _ -> first snd <$> postHelper form env
lastInvalidPostSessionKey :: Text
lastInvalidPostSessionKey = "lastInvalidPost"
-- Sets the post data retreived from postEnv, ignoring the FileEnv.
setLastInvalidPost :: MonadHandler m => Maybe (Env, FileEnv) -> m ()
setLastInvalidPost Nothing = return ()
setLastInvalidPost (Just (env, _)) = sessionSetter lastInvalidPostSessionKey env
-- Retrieves the previous post data to be passed to postHelper.
getLastInvalidPost :: MonadHandler m => m (Maybe (Env, FileEnv))
getLastInvalidPost = do
result <- sessionGetter lastInvalidPostSessionKey
return $ case result of
Nothing -> Nothing
Just env -> Just (env, Map.fromList [])
sessionSetter :: (MonadHandler m, Show a) => Text -> a -> m ()
sessionSetter key = setSession key . pack . show
sessionGetter :: (MonadHandler m, Read b) => Text -> m (Maybe b)
sessionGetter key = do
m <- lookupSession key
return $ readMaybe . unpack =<< m