hello-forms.hs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. {-# LANGUAGE OverloadedStrings #-}
  2. {-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
  3. {-# LANGUAGE QuasiQuotes, TypeFamilies, TemplateHaskell, MultiParamTypeClasses #-}
  4. import Yesod.Core
  5. import Yesod.Form
  6. import Yesod.Form.Nic
  7. import Yesod.Form.MassInput
  8. import Control.Applicative
  9. import Data.Text (Text, pack)
  10. import Network.Wai.Handler.Warp (run)
  11. import Data.Time (utctDay, getCurrentTime)
  12. import qualified Data.Text as T
  13. import Control.Monad.IO.Class (liftIO)
  14. import Text.Blaze.Html.Renderer.String (renderHtml)
  15. data Fruit = Apple | Banana | Pear
  16. deriving (Show, Enum, Bounded, Eq)
  17. fruits :: [(Text, Fruit)]
  18. fruits = map (\x -> (pack $ show x, x)) [minBound..maxBound]
  19. mkYesod "HelloForms" [parseRoutes|
  20. / RootR GET
  21. /mass MassR GET
  22. /valid ValidR GET
  23. /file FileR GET POST
  24. |]
  25. myForm = fixType $ runFormGet $ renderDivs $ pure (,,,,,,,,,,,,)
  26. <*> pure "pure works!"
  27. <*> areq boolField "Bool field" Nothing
  28. <*> aopt boolField "Opt bool field" Nothing
  29. <*> areq textField "Text field" Nothing
  30. <*> areq (selectFieldList fruits) "Select field" Nothing
  31. <*> aopt (selectFieldList fruits) "Opt select field" Nothing
  32. <*> areq (multiSelectFieldList fruits) "Multi select field" Nothing
  33. <*> aopt (multiSelectFieldList fruits) "Opt multi select field" Nothing
  34. <*> aopt intField "Opt int field" Nothing
  35. <*> aopt (radioFieldList fruits) "Opt radio" Nothing
  36. <*> aopt multiEmailField "Opt multi email" Nothing
  37. <*> areq nicHtmlField "NIC HTML" Nothing
  38. <*> aopt timeField "Opt Time" Nothing
  39. instance Show Html where
  40. show = renderHtml
  41. data HelloForms = HelloForms
  42. instance RenderMessage HelloForms FormMessage where
  43. renderMessage _ _ = defaultFormMessage
  44. instance Yesod HelloForms
  45. instance YesodNic HelloForms
  46. fixType :: Handler a -> Handler a
  47. fixType = id
  48. getRootR = do
  49. ((res, form), enctype) <- myForm
  50. defaultLayout [whamlet|
  51. <p>Result: #{show res}
  52. <form enctype=#{enctype}>
  53. ^{form}
  54. <div>
  55. <input type=submit>
  56. <p>
  57. <a href=@{MassR}>See the mass form
  58. <p>
  59. <a href=@{ValidR}>Validation form
  60. <p>
  61. <a href=@{FileR}>File form
  62. |]
  63. myMassForm = fixType $ runFormGet $ renderTable $ inputList "People" massTable
  64. (\x -> (,)
  65. <$> areq textField "Name" (fmap fst x)
  66. <*> areq intField "Age" (fmap snd x)) (Just [("Michael", 26)])
  67. getMassR = do
  68. ((res, form), enctype) <- myMassForm
  69. defaultLayout [whamlet|
  70. <p>Result: #{show res}
  71. <form enctype=#{enctype}>
  72. <table>
  73. ^{form}
  74. <div>
  75. <input type=submit>
  76. <p>
  77. <a href=@{RootR}>See the regular form
  78. |]
  79. myValidForm = fixType $ runFormGet $ renderTable $ pure (,,)
  80. <*> areq (check (\x ->
  81. if T.length x < 3
  82. then Left ("Need at least 3 letters" :: Text)
  83. else Right x
  84. ) textField)
  85. "Name" Nothing
  86. <*> areq (checkBool (>= 18) ("Must be 18 or older" :: Text) intField)
  87. "Age" Nothing
  88. <*> areq (checkM inPast dayField) "Anniversary" Nothing
  89. where
  90. inPast x = do
  91. now <- liftIO $ getCurrentTime
  92. return $ if utctDay now < x
  93. then Left ("Need a date in the past" :: Text)
  94. else Right x
  95. getValidR = do
  96. ((res, form), enctype) <- myValidForm
  97. defaultLayout [whamlet|
  98. <p>Result: #{show res}
  99. <form enctype=#{enctype}>
  100. <table>
  101. ^{form}
  102. <div>
  103. <input type=submit>
  104. <p>
  105. <a href=@{RootR}>See the regular form
  106. |]
  107. main = toWaiApp HelloForms >>= run 3000
  108. fileForm = renderTable $ pure (,)
  109. <*> (FileInfo' <$> areq fileField "Required file" Nothing)
  110. <*> (fmap FileInfo' <$> aopt fileField "Optional file" Nothing)
  111. newtype FileInfo' = FileInfo' FileInfo
  112. instance Show FileInfo' where
  113. show (FileInfo' f) = show (fileName f, fileContentType f)
  114. getFileR = do
  115. ((res, form), enctype) <- runFormPost fileForm
  116. defaultLayout [whamlet|
  117. <p>Result: #{show res}
  118. <form method=post enctype=#{enctype}>
  119. <table>
  120. ^{form}
  121. <tr>
  122. <td>
  123. <input type=submit>
  124. <p>
  125. <a href=@{RootR}>See the regular form
  126. |]
  127. postFileR = getFileR