@@ -3,16 +3,18 @@ module Lumi.Components.Examples.Form where
3
3
import Prelude
4
4
5
5
import Control.Coroutine.Aff (close , emit , produceAff )
6
+ import Control.MonadZero (guard )
6
7
import Data.Array as Array
8
+ import Data.Foldable (foldMap )
7
9
import Data.Int as Int
8
10
import Data.Lens (iso )
9
11
import Data.Lens.Record (prop )
10
12
import Data.Maybe (Maybe (..), fromMaybe , isJust , maybe )
11
- import Data.Monoid ( guard )
13
+ import Data.Monoid as Monoid
12
14
import Data.Newtype (class Newtype , un )
13
15
import Data.Nullable as Nullable
14
16
import Data.String as String
15
- import Data.String.NonEmpty (length , NonEmptyString , toString )
17
+ import Data.String.NonEmpty (NonEmptyString , appendString , length , toString )
16
18
import Data.Symbol (SProxy (..))
17
19
import Effect (Effect )
18
20
import Effect.Aff (Aff , Milliseconds (..), delay , error , throwError )
@@ -24,6 +26,7 @@ import Lumi.Components.Example (example)
24
26
import Lumi.Components.Form (FormBuilder , Validated )
25
27
import Lumi.Components.Form as F
26
28
import Lumi.Components.Form.Defaults (formDefaults )
29
+ import Lumi.Components.Form.Table as FT
27
30
import Lumi.Components.Input as Input
28
31
import Lumi.Components.LabeledField (labeledField , RequiredField (..))
29
32
import Lumi.Components.Modal (dialog )
@@ -56,7 +59,7 @@ docs = unit # make component { initialState, render }
56
59
where
57
60
initialState =
58
61
{ user: (formDefaults :: User )
59
- { favoriteColor = Just " red"
62
+ { leastFavoriteColors = [ " red" ]
60
63
}
61
64
, result: Nothing :: Maybe ValidatedUser
62
65
, modalOpen: false
@@ -208,6 +211,9 @@ docs = unit # make component { initialState, render }
208
211
" red" -> pure { label: " Red" , value: " red" }
209
212
" green" -> pure { label: " Green" , value: " green" }
210
213
" 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" }
211
217
_ -> throwError (error " No color" )
212
218
213
219
loadColors simulatePauses search = do
@@ -217,6 +223,9 @@ docs = unit # make component { initialState, render }
217
223
[ { label: " Red" , value: " red" }
218
224
, { label: " Green" , value: " green" }
219
225
, { label: " Blue" , value: " blue" }
226
+ , { label: " Brown" , value: " brown" }
227
+ , { label: " Black" , value: " black" }
228
+ , { label: " White" , value: " white" }
220
229
]
221
230
222
231
data Country
@@ -249,7 +258,7 @@ type User =
249
258
, admin :: Boolean
250
259
, height :: Validated String
251
260
, addresses :: Validated (Array Address )
252
- , favoriteColor :: Maybe String
261
+ , pets :: Validated ( Array Pet )
253
262
, leastFavoriteColors :: Array String
254
263
, notes :: String
255
264
, avatar :: Maybe Upload.FileId
@@ -262,11 +271,27 @@ type ValidatedUser =
262
271
, admin :: Boolean
263
272
, height :: Maybe Number
264
273
, addresses :: Array ValidatedAddress
265
- , favoriteColor :: Maybe String
274
+ , pets :: Array ValidatedPet
275
+ , leastFavoriteColors :: Array String
266
276
, notes :: String
267
277
, avatar :: Maybe Upload.FileId
268
278
}
269
279
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
+
270
295
-- | We have to fully apply `Form.build` in order to avoid
271
296
-- | remounting this component on each render.
272
297
userComponent
@@ -296,7 +321,7 @@ userForm = ado
296
321
F .indent " First Name" Required
297
322
$ F .focus (prop (SProxy :: SProxy " firstName" ))
298
323
$ F .warn (\x ->
299
- guard
324
+ Monoid . guard
300
325
(length x <= 2 )
301
326
(pure " First name should be longer than two characters (but it doesn't have to be)." )
302
327
)
@@ -335,25 +360,14 @@ userForm = ado
335
360
addresses <-
336
361
F .focus (prop (SProxy :: SProxy " addresses" ))
337
362
$ F .warn (\as ->
338
- guard (Array .null as) (pure " No address added." )
363
+ Monoid . guard (Array .null as) (pure " No address added." )
339
364
)
340
365
$ F .array
341
366
{ label: " Address"
342
367
, addLabel: " Add address"
343
368
, defaultValue: formDefaults
344
369
, editor: addressForm
345
370
}
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)
357
371
leastFavoriteColors <-
358
372
F .indent " Least Favorite Colors" Neither
359
373
$ F .focus (prop (SProxy :: SProxy " leastFavoriteColors" ))
@@ -371,6 +385,85 @@ userForm = ado
371
385
$ F .focus (prop (SProxy :: SProxy " notes" ))
372
386
$ F .textarea
373
387
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
+
374
467
F .section " Images"
375
468
avatar <-
376
469
F .indent " Avatar" Optional
@@ -403,8 +496,9 @@ userForm = ado
403
496
, password
404
497
, admin
405
498
, height
499
+ , pets
500
+ , leastFavoriteColors
406
501
, addresses
407
- , favoriteColor
408
502
, notes
409
503
, avatar
410
504
}
0 commit comments