Home > Blockchain >  Haskell Yesod: Sending a Post Request On Image Click
Haskell Yesod: Sending a Post Request On Image Click

Time:01-28

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.

CodePudding user response:

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
  • Related