haskellhappstackreformformlets

When creating a form with the Reform library, how do I put all the errors in a single list?


I'm following the tutorial for the reform library. I currently have a form with two required fields and its set up so the error message for each field shows up right next to it.

postForm :: MyForm MyRequest
postForm = 
    MyRequest <$> name <*> msg <* inputSubmit "post it!"
  where
    name = labelText "name:"  ++>
            (inputText "" `transformEither` required "Name is required") <++ br <++ errorList
    msg  = labelText "message:" ++>
            (inputText "" `transformEither` required "Message is required") <++ br <++ errorList

For example, if I submit this form empty the validation will fail and it will ask the user to fill it again and it will look like this:

name: [______]
  * Name is Required
message: [_____]
  * Message is required

I would like to know how to make a single error list for the form, like this:

name: [______]
message: [_____]
  * Name is Required
  * Message is required

I tried doing

postForm :: MyForm MyRequest
postForm =
    (MyRequest <$> name <*> msg <* inputSubmit "post it!") <++ errorList
  where
    name = labelText "name:"  ++>
            (inputText "" `transformEither` required "Name is required") <++ br
    msg  = labelText "message:" ++>
            (inputText "" `transformEither` required "Message is required") <++ br

but then the error messages don't show at all!


I'm not including a full runnable example because there is a bunch of extra boilerplate needed for that and I am hoping that my problem is just a matter of undertanding the applicative notation a bit better. Here are the type signatures for some of the functions involved in case that helps:

type MyForm = Form (ServerPartT IO) [Input] ReqError H.Html ()

<++ :: (Monad m, Monoid view)
    => Form m input error view proof a
    -> Form m input error view () ()
    -> Form m input error view proof a

errorList :: (Monad m, ToMarkup error)
    => Form m input error Html () ()

http://hackage.haskell.org/package/reform-0.2.1/docs/Text-Reform-Core.html#v:-60--43--43-

http://hackage.haskell.org/package/reform-blaze-0.2.0/docs/Text-Reform-Blaze-Common.html#v:errorList


Solution

  • Instead of using the errorList function, use childErrorList. It will also include errors from the subforms.

    (MyRequest <$> name <*> msg <* inputSubmit "post it!") <++ childErrorList
    

    The parenthesis around the parent form are important. If you do

    MyRequest <$> name <*> msg <* inputSubmit "post it!" <++ childErrorList
    

    then the operator precedences make it so that childErrorList only gets errors from the submit button (none at all) instead of from the whole form.