Skip to content

Commit dd945dd

Browse files
Move prop requirements to arguments in Form.asyncSelect (#55)
1 parent 8ef3f89 commit dd945dd

File tree

2 files changed

+47
-92
lines changed

2 files changed

+47
-92
lines changed

docs/Examples/Form.example.purs

Lines changed: 36 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import Data.String as String
1717
import Data.String.NonEmpty (NonEmptyString, appendString, length, toString)
1818
import Data.Symbol (SProxy(..))
1919
import Effect (Effect)
20-
import Effect.Aff (Aff, Milliseconds(..), delay, error, throwError)
20+
import Effect.Aff (Milliseconds(..), delay, error, throwError)
2121
import Effect.Class (liftEffect)
2222
import Effect.Random (randomRange)
2323
import Lumi.Components.Button as Button
@@ -85,9 +85,8 @@ docs = unit # make component { initialState, render }
8585
SetUser update ->
8686
let
8787
formProps =
88-
{ loadColor: loadColor self.state.simulatePauses
89-
, loadColors: loadColors self.state.simulatePauses
90-
, readonly: self.state.readonly
88+
{ readonly: self.state.readonly
89+
, simulatePauses: self.state.simulatePauses
9190
}
9291
in
9392
self.setState \s -> s
@@ -166,11 +165,10 @@ docs = unit # make component { initialState, render }
166165
[ userComponent
167166
{ value: user
168167
, onChange: send self <<< SetUser
169-
, loadColor: loadColor simulatePauses
170-
, loadColors: loadColors simulatePauses
171168
, inlineTable
172169
, forceTopLabels: forceTopLabels && not inlineTable
173170
, readonly
171+
, simulatePauses
174172
}
175173
, row
176174
{ style: css { justifyContent: "flex-end" }
@@ -204,30 +202,6 @@ docs = unit # make component { initialState, render }
204202
}
205203
]
206204

207-
loadColor simulatePauses c = do
208-
when simulatePauses do
209-
delay (Milliseconds 500.0)
210-
case String.toLower c of
211-
"red" -> pure { label: "Red", value: "red" }
212-
"green" -> pure { label: "Green", value: "green" }
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" }
217-
_ -> throwError (error "No color")
218-
219-
loadColors simulatePauses search = do
220-
when simulatePauses do
221-
delay (Milliseconds 1000.0)
222-
pure
223-
[ { label: "Red", value: "red" }
224-
, { label: "Green", value: "green" }
225-
, { label: "Blue", value: "blue" }
226-
, { label: "Brown", value: "brown" }
227-
, { label: "Black", value: "black" }
228-
, { label: "White", value: "white" }
229-
]
230-
231205
data Country
232206
= BR
233207
| US
@@ -297,21 +271,19 @@ type ValidatedPet =
297271
userComponent
298272
:: { value :: User
299273
, onChange :: (User -> User) -> Effect Unit
300-
, loadColor :: String -> Aff { label :: String, value :: String }
301-
, loadColors :: String -> Aff (Array { label :: String, value :: String })
302274
, inlineTable :: Boolean
303275
, forceTopLabels :: Boolean
304276
, readonly :: Boolean
277+
, simulatePauses :: Boolean
305278
}
306279
-> JSX
307280
userComponent = F.build userForm
308281

309282
userForm
310283
:: forall props
311284
. FormBuilder
312-
{ loadColor :: String -> Aff { label :: String, value :: String }
313-
, loadColors :: String -> Aff (Array { label :: String, value :: String })
314-
, readonly :: Boolean
285+
{ readonly :: Boolean
286+
, simulatePauses :: Boolean
315287
| props
316288
}
317289
User
@@ -448,14 +420,15 @@ userForm = ado
448420
}
449421
color <-
450422
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)
423+
$ F.withProps \props ->
424+
F.focus (prop (SProxy :: SProxy "color"))
425+
$ F.asyncSelectByKey
426+
(loadColor props.simulatePauses)
427+
(loadColors props.simulatePauses)
428+
identity
429+
identity
430+
identity
431+
(R.text <<< _.label)
459432
in
460433
{ name
461434
, animal
@@ -507,6 +480,26 @@ userForm = ado
507480
interval <- liftEffect $ randomRange 100.0 700.0
508481
delay $ Milliseconds interval
509482

483+
loadColor simulatePauses c = do
484+
when simulatePauses do
485+
randomPause
486+
case String.toLower c of
487+
"red" -> pure { label: "Red", value: "red" }
488+
"green" -> pure { label: "Green", value: "green" }
489+
"blue" -> pure { label: "Blue", value: "blue" }
490+
_ -> throwError (error "No color")
491+
492+
loadColors simulatePauses search = do
493+
when simulatePauses do
494+
randomPause
495+
randomPause
496+
pure
497+
[ { label: "Red", value: "red" }
498+
, { label: "Green", value: "green" }
499+
, { label: "Blue", value: "blue" }
500+
]
501+
502+
510503
type Address =
511504
{ name :: Validated String
512505
, street :: Validated String

src/Lumi/Components/Form.purs

Lines changed: 11 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,12 @@ import Lumi.Components.Select as Select
8282
import Lumi.Components.Text (body, body_, subsectionHeader, text)
8383
import Lumi.Components.Textarea as Textarea
8484
import Lumi.Components.Upload as Upload
85-
import Prim.Row (class Nub, class Union, class Cons)
85+
import Prim.Row (class Nub, class Union)
8686
import React.Basic (JSX, createComponent, element, empty, fragment, keyed, makeStateless)
8787
import React.Basic.Components.Async (async, asyncWithLoader)
8888
import React.Basic.DOM as R
8989
import React.Basic.DOM.Events (capture, stopPropagation, targetChecked, targetValue)
9090
import React.Basic.Events as Events
91-
import Record (get)
9291
import Unsafe.Coerce (unsafeCoerce)
9392

9493
-- | Create a React component for a form from a `FormBuilder`.
@@ -394,38 +393,13 @@ multiSelect encode opts = formBuilder_ \{ readonly } selected onChange ->
394393

395394
-- | An editor which uses an API call to populate a single-select
396395
-- | drop-down.
397-
-- |
398-
-- | The API call is made available in props using the `RowCons`
399-
-- | constraint. Pass an `SProxy` to specify the label where the API
400-
-- | call will be stored.
401-
-- |
402-
-- | For example:
403-
-- |
404-
-- | ```purescript
405-
-- | asyncSelect (SProxy :: SProxy "foo")
406-
-- | :: forall props additionalData
407-
-- | . (Select.SelectOption additionalData -> JSX)
408-
-- | -> FormBuilder
409-
-- | { readonly :: Boolean
410-
-- | , foo :: String -> Aff (Either String
411-
-- | (Array (Select.SelectOption additionalData)))
412-
-- | | props
413-
-- | }
414-
-- | (Maybe (Select.SelectOption))
415-
-- | ```
416396
asyncSelect
417-
:: forall l props rest a
418-
. IsSymbol l
419-
=> Cons
420-
l
421-
(String -> Aff (Array a))
422-
rest
423-
(readonly :: Boolean | props)
424-
=> SProxy l
397+
:: forall props a
398+
. (String -> Aff (Array a))
425399
-> (a -> Select.SelectOption)
426400
-> (a -> JSX)
427401
-> FormBuilder { readonly :: Boolean | props } (Maybe a) (Maybe a)
428-
asyncSelect l toSelectOption optionRenderer =
402+
asyncSelect loadOptions toSelectOption optionRenderer =
429403
formBuilder_ \props@{ readonly } value onChange ->
430404
if readonly
431405
then case value of
@@ -437,7 +411,7 @@ asyncSelect l toSelectOption optionRenderer =
437411

438412
else Select.asyncSingleSelect
439413
{ value
440-
, loadOptions: get l props
414+
, loadOptions
441415
, onChange: onChange
442416
, className: ""
443417
, style: R.css {}
@@ -455,30 +429,18 @@ asyncSelect l toSelectOption optionRenderer =
455429

456430
-- | Similar to `asyncSelect` but allows the current value to be specified using only its key.
457431
asyncSelectByKey
458-
:: forall k l props rest1 rest2 id a
459-
. IsSymbol k
460-
=> IsSymbol l
461-
=> Cons
462-
k
463-
(id -> Aff a)
464-
rest1
465-
(readonly :: Boolean | props)
466-
=> Cons
467-
l
468-
(String -> Aff (Array a))
469-
rest2
470-
(readonly :: Boolean | props)
471-
=> SProxy k
472-
-> SProxy l
432+
:: forall props id a
433+
. (id -> Aff a)
434+
-> (String -> Aff (Array a))
473435
-> (id -> String)
474436
-> (String -> id)
475437
-> (a -> Select.SelectOption)
476438
-> (a -> JSX)
477439
-> FormBuilder { readonly :: Boolean | props } (Maybe id) (Maybe id)
478-
asyncSelectByKey k l fromId toId toSelectOption optionRenderer =
440+
asyncSelectByKey getData loadOptions fromId toId toSelectOption optionRenderer =
479441
formBuilder_ \props@{ readonly } value onChange ->
480442
FetchCache.single
481-
{ getData: \key -> get k props (toId key)
443+
{ getData: getData <<< toId
482444
, id: map fromId value
483445
, render: \data_ ->
484446
if readonly
@@ -496,7 +458,7 @@ asyncSelectByKey k l fromId toId toSelectOption optionRenderer =
496458
else
497459
Select.asyncSingleSelect
498460
{ value: data_
499-
, loadOptions: get l props
461+
, loadOptions
500462
, onChange: onChange <<< map (toId <<< _.value <<< toSelectOption)
501463
, className: ""
502464
, style: R.css {}

0 commit comments

Comments
 (0)