yesod-examples 0.5.0 → 0.5.0.1
raw patch · 3 files changed
+129/−2 lines, 3 filesdep +timedep ~yesodnew-component:exe:formnew-component:exe:mkToForm
Dependencies added: time
Dependency ranges changed: yesod
Files
- yesod-examples.cabal +9/−2
- yesod/tutorial/form.lhs +48/−0
- yesod/tutorial/mkToForm.hs +72/−0
yesod-examples.cabal view
@@ -1,5 +1,5 @@ Name: yesod-examples-Version: 0.5.0+Version: 0.5.0.1 Synopsis: Example programs using the Yesod Web Framework. Description: These are the same examples and tutorials found on the documentation site. Homepage: http://docs.yesodweb.com/@@ -17,7 +17,7 @@ Executable helloworld Main-is: yesod/helloworld.lhs Build-depends: base >= 4 && < 5,- yesod >= 0.5.0 && < 0.6+ yesod >= 0.5.0.1 && < 0.6 Executable blog Main-is: yesod/tutorial/blog.lhs@@ -42,6 +42,13 @@ Executable widgets Main-is: yesod/tutorial/widgets.lhs++Executable form+ Main-is: yesod/tutorial/form.lhs++Executable mkToForm+ Main-is: yesod/tutorial/mkToForm.hs+ Build-depends: time Executable persistent-synopsis Main-is: persistent/synopsis.lhs
+ yesod/tutorial/form.lhs view
@@ -0,0 +1,48 @@+Forms can be a tedious part of web development since they require synchronization of code in many different areas: the HTML form declaration, parsing of the form and reconstructing a datatype from the raw values. The Yesod form library simplifies things greatly. We'll start off with a basic application.+++> {-# LANGUAGE TypeFamilies, QuasiQuotes, OverloadedStrings #-}+> import Yesod+> import Control.Applicative+> data FormExample = FormExample+> type Handler = GHandler FormExample FormExample+> mkYesod "FormExample" [$parseRoutes|+> / RootR GET+> |]+> instance Yesod FormExample where approot _ = ""++Next, we'll declare a Person datatype with a name and age. After that, we'll create a formlet. A formlet is a declarative approach to forms. It takes a Maybe value and constructs either a blank form, a form based on the original value, or a form based on the values submitted by the user. It also attempts to construct a datatype, failing on validation errors.++> data Person = Person { name :: String, age :: Int }+> deriving Show+> personFormlet p = fieldsToTable $ Person+> <$> stringField "Name" (fmap name p)+> <*> intField "Age" (fmap age p)++We use an applicative approach and stay mostly declarative. The "fmap name p" bit is just a way to get the name from within a value of type "Maybe Person".++> getRootR :: Handler RepHtml+> getRootR = do+> (res, wform, enctype) <- runFormGet $ personFormlet Nothing++We use runFormGet to bind to GET (query-string) parameters; we could also use runFormPost. The "Nothing" is the initial value of the form. You could also supply a "Just Person" value if you like. There is a three-tuple returned, containing the parsed value, the HTML form as a widget and the encoding type for the form.++We use a widget for the form since it allows embedding CSS and Javascript code in forms directly. This allows unobtrusive adding of rich Javascript controls like date pickers.++> defaultLayout $ do+> setTitle "Form Example"+> form <- extractBody wform++extractBody returns the HTML of a widget and "passes" all of the other declarations (the CSS, Javascript, etc) up to the parent widget. The rest of this is just standard Hamlet code and our main function.++> addBody [$hamlet|+> %p Last result: $show.res$+> %form!enctype=$enctype$+> %table+> ^form^+> %tr+> %td!colspan=2+> %input!type=submit+> |]+> +> main = basicHandler 3000 FormExample
+ yesod/tutorial/mkToForm.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE TypeFamilies, QuasiQuotes, GeneralizedNewtypeDeriving #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+import Yesod+import Yesod.Helpers.Crud+import Yesod.Form.Jquery+import Yesod.Form.Nic+import Database.Persist.Sqlite+import Database.Persist.TH+import Data.Time (Day)++share2 mkToForm mkPersist [$persist|+Entry+ title String+ day Day Desc toFormField=YesodJquery.jqueryDayField+ content Html toFormField=YesodNic.nicHtmlField+ deriving+|]++instance Item Entry where+ itemTitle = entryTitle++data Blog = Blog { pool :: ConnectionPool }++type EntryCrud = Crud Blog Entry++mkYesod "Blog" [$parseRoutes|+/ RootR GET+/entry/#EntryId EntryR GET+/admin AdminR EntryCrud defaultCrud+|]++instance Yesod Blog where+ approot _ = "http://localhost:3000"++instance YesodPersist Blog where+ type YesodDB Blog = SqlPersist+ runDB db = fmap pool getYesod >>= runSqlPool db++instance YesodJquery Blog+instance YesodNic Blog++getRootR = do+ entries <- runDB $ selectList [] [EntryDayDesc] 0 0+ defaultLayout $ do+ setTitle $ string "Yesod Blog Tutorial Homepage"+ addBody [$hamlet|+%h1 Archive+%ul+ $forall entries entry+ %li+ %a!href=@EntryR.fst.entry@ $entryTitle.snd.entry$+%p+ %a!href=@AdminR.CrudListR@ Admin+|]++getEntryR entryid = do+ entry <- runDB $ get404 entryid+ defaultLayout $ do+ setTitle $ string $ entryTitle entry+ addBody [$hamlet|+%h1 $entryTitle.entry$+%h2 $show.entryDay.entry$+$entryContent.entry$+|]++withBlog f = withSqlitePool "blog.db3" 8 $ \pool -> do+ flip runSqlPool pool $ runMigration $ do+ migrate (undefined :: Entry)+ f $ Blog pool++main = withBlog $ basicHandler 3000