From 68d0142dda7d7031f906e7db03b96959ced8957a Mon Sep 17 00:00:00 2001 From: Felipe Lessa Date: Wed, 12 Mar 2014 11:20:31 -0300 Subject: [PATCH 1/3] New identifyForm function (fixes #649). Based on code from @axel-angel but rewritten in a more lightweight style (IMHO, at least :). --- yesod-form/Yesod/Form/Functions.hs | 58 +++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/yesod-form/Yesod/Form/Functions.hs b/yesod-form/Yesod/Form/Functions.hs index 8785cbc9..f033d6f6 100644 --- a/yesod-form/Yesod/Form/Functions.hs +++ b/yesod-form/Yesod/Form/Functions.hs @@ -24,6 +24,8 @@ module Yesod.Form.Functions -- * Generate a blank form , generateFormPost , generateFormGet + -- * More than one form on a handler + , identifyForm -- * Rendering , FormRender , renderTable @@ -45,7 +47,7 @@ module Yesod.Form.Functions import Yesod.Form.Types import Data.Text (Text, pack) import Control.Arrow (second) -import Control.Monad.Trans.RWS (ask, get, put, runRWST, tell, evalRWST) +import Control.Monad.Trans.RWS (ask, get, put, runRWST, tell, evalRWST, local) import Control.Monad.Trans.Class import Control.Monad (liftM, join) import Crypto.Classes (constTimeEq) @@ -285,6 +287,60 @@ getHelper form env = do m <- getYesod runFormGeneric (form fragment) m langs env + +-- | Creates a hidden field on the form that identifies it. This +-- identification is then used to distinguish between /missing/ +-- and /wrong/ form data when a single handler contains more than +-- one form. +-- +-- For instance, if you have the following code on your handler: +-- +-- > ((fooRes, fooWidget), fooEnctype) <- runFormPost fooForm +-- > ((barRes, barWidget), barEnctype) <- runFormPost barForm +-- +-- Then replace it with +-- +-- > ((fooRes, fooWidget), fooEnctype) <- runFormPost $ identifyForm "foo" fooForm +-- > ((barRes, barWidget), barEnctype) <- runFormPost $ identifyForm "bar" barForm +-- +-- Note that it's your responsibility to ensure that the +-- identication strings are unique (using the same one twice on a +-- single handler will not generate any errors). This allows you +-- to create a variable number of forms and still have them work +-- even if their number or order change between the HTML +-- generation and the form submission. +identifyForm + :: Monad m + => Text -- ^ Form identification string. + -> (Html -> MForm m (FormResult a, WidgetT (HandlerSite m) IO ())) + -> (Html -> MForm m (FormResult a, WidgetT (HandlerSite m) IO ())) +identifyForm identVal form = \fragment -> do + -- Create hidden . + let fragment' = + [shamlet| + + #{fragment} + |] + + -- Check if we got its value back. + mp <- askParams + let missing = + case mp of + Just params -> Map.lookup identifyFormKey params /= Just [identVal] + Nothing -> True + + -- Run the form proper (with our hidden ). If the + -- data is missing, then do not provide any params to the + -- form, which will turn its result into FormMissing. Also, + -- doing this avoids having lots of fields with red errors. + let eraseParams | missing = local (\(_, h, l) -> (Nothing, h, l)) + | otherwise = id + eraseParams (form fragment') + +identifyFormKey :: Text +identifyFormKey = "_formid" + + type FormRender m a = AForm m a -> Html From 3d2253d5d3d5e5c92c8f09c2cc179b86689e8a83 Mon Sep 17 00:00:00 2001 From: Felipe Lessa Date: Wed, 12 Mar 2014 11:23:32 -0300 Subject: [PATCH 2/3] Typo. --- yesod-form/Yesod/Form/Functions.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yesod-form/Yesod/Form/Functions.hs b/yesod-form/Yesod/Form/Functions.hs index f033d6f6..ead60fc9 100644 --- a/yesod-form/Yesod/Form/Functions.hs +++ b/yesod-form/Yesod/Form/Functions.hs @@ -304,7 +304,7 @@ getHelper form env = do -- > ((barRes, barWidget), barEnctype) <- runFormPost $ identifyForm "bar" barForm -- -- Note that it's your responsibility to ensure that the --- identication strings are unique (using the same one twice on a +-- identification strings are unique (using the same one twice on a -- single handler will not generate any errors). This allows you -- to create a variable number of forms and still have them work -- even if their number or order change between the HTML From 969496b9f1a855bc4605f7aa49dc57545f02c25d Mon Sep 17 00:00:00 2001 From: Felipe Lessa Date: Wed, 12 Mar 2014 11:32:46 -0300 Subject: [PATCH 3/3] Golf around on identifyForm :). --- yesod-form/Yesod/Form/Functions.hs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/yesod-form/Yesod/Form/Functions.hs b/yesod-form/Yesod/Form/Functions.hs index ead60fc9..69122a7b 100644 --- a/yesod-form/Yesod/Form/Functions.hs +++ b/yesod-form/Yesod/Form/Functions.hs @@ -324,10 +324,7 @@ identifyForm identVal form = \fragment -> do -- Check if we got its value back. mp <- askParams - let missing = - case mp of - Just params -> Map.lookup identifyFormKey params /= Just [identVal] - Nothing -> True + let missing = (mp >>= Map.lookup identifyFormKey) /= Just [identVal] -- Run the form proper (with our hidden ). If the -- data is missing, then do not provide any params to the