I am writing a simple website in Haskell with Yesod. I have the following hamlet
<ul id="gallery">
$forall file <- listOfFiles
<form action=@{CharacterUpdateR} method="POST">
<input type="hidden" name="Name" value=#{characterName character} />
<input type="hidden" name="Portrait" value=#{file} />
<input type="hidden" name="Description" value=#{fromMaybe "" (characterDescription character)} />
<input type="image" src=#{imageFilePath $ (++) (unpack $ characterName character) ((++) "\\" file)} name="select" alt="select" />
The following Haskell code is supposed to handle the request:
postCharacterUpdateR :: Handler Html
postCharacterUpdateR = do
((result, widget), enctype) <- runFormPost updateCharacterForm
case result of
FormSuccess (name, file, desc) -> do
_ <- runDB $ updateWhere [CharacterName ==. name] [CharacterPortrait =. file]
_ <- runDB $ updateWhere [CharacterName ==. name] [CharacterDescription =. desc]
setMessage "Character Updated"
redirect CharactersR
_ -> do
liftIO $ putStrLn $ show result
setMessage $ "Something went wrong: "
redirect CharactersR
The page renders fine and when the images in the gallery are clicked, a POST request is sent and received by the handler, but it always fails, with the following error message: FormFailure ["Value is required","Value is required"]
I have tried to send the post request via a Julius widget instead with ajax, but reached a similar problem. In the developer console, it seems like the payload for the sent POST request is fine, but nonetheless the handler never receives the POST parameters.
I fixed this issue by, rather than using Hamlet itself to create the form submission, using runFormPost to get a widget to send the request.
updateCharacterForm :: Text -> String -> Maybe Textarea -> Html -> MForm Handler (FormResult (Text, Text, Maybe Textarea), Widget)
updateCharacterForm name portrait desc = renderBootstrap $ (,,)
<$> areq hiddenField "Name" (Just name)
<*> areq hiddenField "Portrait" (Just $ pack portrait)
<*> aopt textareaField "Description" (Just desc)
In conjunction with
characterGalleryEntry :: Character -> String -> Widget
characterGalleryEntry character file = do
((_, widget), enctype) <- liftHandler $ runFormPost (updateCharacterForm (characterName character) file (characterDescription character))
[whamlet|$newline never
<form action=@{CharacterUpdateR} method=post enctype=#{enctype}>
^{widget}
<image src=#{imageFilePath $ (++) (unpack $ characterName character) ((++) "\\" file)}>
<input .btn type=submit value="Set Profile Picture and Update">
|]```
For the post itself