@@ -3,16 +3,18 @@ module Lumi.Components.Examples.Form where
33import Prelude
44
55import Control.Coroutine.Aff (close , emit , produceAff )
6+ import Control.MonadZero (guard )
67import Data.Array as Array
8+ import Data.Foldable (foldMap )
79import Data.Int as Int
810import Data.Lens (iso )
911import Data.Lens.Record (prop )
1012import Data.Maybe (Maybe (..), fromMaybe , isJust , maybe )
11- import Data.Monoid ( guard )
13+ import Data.Monoid as Monoid
1214import Data.Newtype (class Newtype , un )
1315import Data.Nullable as Nullable
1416import Data.String as String
15- import Data.String.NonEmpty (length , NonEmptyString , toString )
17+ import Data.String.NonEmpty (NonEmptyString , appendString , length , toString )
1618import Data.Symbol (SProxy (..))
1719import Effect (Effect )
1820import Effect.Aff (Aff , Milliseconds (..), delay , error , throwError )
@@ -24,6 +26,7 @@ import Lumi.Components.Example (example)
2426import Lumi.Components.Form (FormBuilder , Validated )
2527import Lumi.Components.Form as F
2628import Lumi.Components.Form.Defaults (formDefaults )
29+ import Lumi.Components.Form.Table as FT
2730import Lumi.Components.Input as Input
2831import Lumi.Components.LabeledField (labeledField , RequiredField (..))
2932import Lumi.Components.Modal (dialog )
@@ -56,7 +59,7 @@ docs = unit # make component { initialState, render }
5659 where
5760 initialState =
5861 { user: (formDefaults :: User )
59- { favoriteColor = Just " red"
62+ { leastFavoriteColors = [ " red" ]
6063 }
6164 , result: Nothing :: Maybe ValidatedUser
6265 , modalOpen: false
@@ -208,6 +211,9 @@ docs = unit # make component { initialState, render }
208211 " red" -> pure { label: " Red" , value: " red" }
209212 " green" -> pure { label: " Green" , value: " green" }
210213 " blue" -> pure { label: " Blue" , value: " blue" }
214+ " brown" -> pure { label: " Brown" , value: " brown" }
215+ " black" -> pure { label: " Black" , value: " black" }
216+ " white" -> pure { label: " White" , value: " white" }
211217 _ -> throwError (error " No color" )
212218
213219 loadColors simulatePauses search = do
@@ -217,6 +223,9 @@ docs = unit # make component { initialState, render }
217223 [ { label: " Red" , value: " red" }
218224 , { label: " Green" , value: " green" }
219225 , { label: " Blue" , value: " blue" }
226+ , { label: " Brown" , value: " brown" }
227+ , { label: " Black" , value: " black" }
228+ , { label: " White" , value: " white" }
220229 ]
221230
222231data Country
@@ -249,7 +258,7 @@ type User =
249258 , admin :: Boolean
250259 , height :: Validated String
251260 , addresses :: Validated (Array Address )
252- , favoriteColor :: Maybe String
261+ , pets :: Validated ( Array Pet )
253262 , leastFavoriteColors :: Array String
254263 , notes :: String
255264 , avatar :: Maybe Upload.FileId
@@ -262,11 +271,27 @@ type ValidatedUser =
262271 , admin :: Boolean
263272 , height :: Maybe Number
264273 , addresses :: Array ValidatedAddress
265- , favoriteColor :: Maybe String
274+ , pets :: Array ValidatedPet
275+ , leastFavoriteColors :: Array String
266276 , notes :: String
267277 , avatar :: Maybe Upload.FileId
268278 }
269279
280+ type Pet =
281+ { firstName :: Validated String
282+ , lastName :: Validated String
283+ , animal :: Validated (Maybe String )
284+ , age :: Validated String
285+ , color :: Maybe String
286+ }
287+
288+ type ValidatedPet =
289+ { name :: NonEmptyString
290+ , animal :: String
291+ , age :: Int
292+ , color :: Maybe String
293+ }
294+
270295-- | We have to fully apply `Form.build` in order to avoid
271296-- | remounting this component on each render.
272297userComponent
@@ -296,7 +321,7 @@ userForm = ado
296321 F .indent " First Name" Required
297322 $ F .focus (prop (SProxy :: SProxy " firstName" ))
298323 $ F .warn (\x ->
299- guard
324+ Monoid . guard
300325 (length x <= 2 )
301326 (pure " First name should be longer than two characters (but it doesn't have to be)." )
302327 )
@@ -335,25 +360,14 @@ userForm = ado
335360 addresses <-
336361 F .focus (prop (SProxy :: SProxy " addresses" ))
337362 $ F .warn (\as ->
338- guard (Array .null as) (pure " No address added." )
363+ Monoid . guard (Array .null as) (pure " No address added." )
339364 )
340365 $ F .array
341366 { label: " Address"
342367 , addLabel: " Add address"
343368 , defaultValue: formDefaults
344369 , editor: addressForm
345370 }
346- favoriteColor <-
347- F .withKey " favoriteColor"
348- $ F .indent " Favorite Color" Neither
349- $ F .focus (prop (SProxy :: SProxy " favoriteColor" ))
350- $ F .asyncSelectByKey
351- (SProxy :: SProxy " loadColor" )
352- (SProxy :: SProxy " loadColors" )
353- identity
354- identity
355- identity
356- (R .text <<< _.label)
357371 leastFavoriteColors <-
358372 F .indent " Least Favorite Colors" Neither
359373 $ F .focus (prop (SProxy :: SProxy " leastFavoriteColors" ))
@@ -371,6 +385,85 @@ userForm = ado
371385 $ F .focus (prop (SProxy :: SProxy " notes" ))
372386 $ F .textarea
373387
388+ F .section " Pets"
389+ pets <-
390+ F .focus (prop (SProxy :: SProxy " pets" ))
391+ $ F .warn (\pets ->
392+ Monoid .guard (Array .null pets) (pure " You should adopt a pet." )
393+ )
394+ $ FT .editableTable
395+ { addLabel: " Add pet"
396+ , defaultValue: Just
397+ { firstName: F.Fresh " "
398+ , lastName: F.Fresh " "
399+ , animal: F.Fresh Nothing
400+ , age: F.Fresh " 1"
401+ , color: Nothing
402+ }
403+ , maxRows: top
404+ , summary: mempty
405+ , formBuilder: ado
406+ name <- FT .column_ " Name" ado
407+ firstName <-
408+ F .focus (prop (SProxy :: SProxy " firstName" ))
409+ $ F .validated (F .nonEmpty " First name" )
410+ $ F .textbox
411+ lastName <-
412+ F .focus (prop (SProxy :: SProxy " lastName" ))
413+ $ F .warn (\lastName -> do
414+ guard (not String .null lastName)
415+ pure " Did you really give your pet a surname?"
416+ )
417+ $ F .textbox
418+ in
419+ appendString firstName
420+ $ foldMap (" " <> _)
421+ $ Monoid .guard (not String .null lastName)
422+ $ Just lastName
423+ animal <-
424+ FT .column_ " Animal"
425+ $ F .focus (prop (SProxy :: SProxy " animal" ))
426+ $ F .validated (F .nonNull " Animal" )
427+ $ F .select identity pure
428+ $ map (\value -> { label: value, value })
429+ [ " Bird"
430+ , " Cat"
431+ , " Cow"
432+ , " Dog"
433+ , " Duck"
434+ , " Fish"
435+ , " Horse"
436+ , " Rabbit"
437+ , " Rat"
438+ , " Turle"
439+ ]
440+ age <-
441+ FT .column_ " Age"
442+ $ F .focus (prop (SProxy :: SProxy " age" ))
443+ $ F .validated (F .validInt " Age" )
444+ $ F .number
445+ { step: Input.Step 1.0
446+ , min: Just 0.0
447+ , max: Nothing
448+ }
449+ color <-
450+ FT .column_ " Color"
451+ $ F .focus (prop (SProxy :: SProxy " color" ))
452+ $ F .asyncSelectByKey
453+ (SProxy :: SProxy " loadColor" )
454+ (SProxy :: SProxy " loadColors" )
455+ identity
456+ identity
457+ identity
458+ (R .text <<< _.label)
459+ in
460+ { name
461+ , animal
462+ , age
463+ , color
464+ }
465+ }
466+
374467 F .section " Images"
375468 avatar <-
376469 F .indent " Avatar" Optional
@@ -403,8 +496,9 @@ userForm = ado
403496 , password
404497 , admin
405498 , height
499+ , pets
500+ , leastFavoriteColors
406501 , addresses
407- , favoriteColor
408502 , notes
409503 , avatar
410504 }
0 commit comments