Skip to content

Commit b42d54e

Browse files
skressthomashoneyman
authored andcommitted
Makes sure that the last captured input is used to run validations instead of the first input (#63)
* Makes sure that the last captured input is used to run validations instead of the first input. * Fix bug when async validation overwrites the other form fields with an old snapshot. unsafeRunValidationVariant in Internal.Transform now returns a function that modifies the form such that this transformation can be run against the current value of the form instead of the old one which was captured before the (possibly async) validations have been run.
1 parent f7ad5ce commit b42d54e

File tree

4 files changed

+27
-16
lines changed

4 files changed

+27
-16
lines changed

src/Formless/Component.purs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,10 @@ handleAction handleAction' handleEvent action = flip match action
237237
, validate: \variant -> do
238238
st <- H.get
239239
let validators = (unwrap st.internal).validators
240-
form <- H.lift do
240+
formProcessor <- H.lift do
241241
IT.unsafeRunValidationVariant variant validators st.form
242-
H.modify_ _ { form = form }
242+
st' <- H.get
243+
H.modify_ _ { form = formProcessor st'.form }
243244
handleAction handleAction' handleEvent sync
244245

245246
, modifyValidate: \(Tuple milliseconds variant) -> do
@@ -255,10 +256,12 @@ handleAction handleAction' handleEvent action = flip match action
255256
validate = do
256257
st <- H.get
257258
let vs = (unwrap st.internal).validators
258-
form <- H.lift do
259+
formProcessor <- H.lift do
259260
IT.unsafeRunValidationVariant (unsafeCoerce variant) vs st.form
260-
H.modify_ _ { form = form }
261-
pure form
261+
st' <- H.get
262+
let newForm = formProcessor st'.form
263+
H.modify_ _ { form = newForm }
264+
pure newForm
262265

263266
case milliseconds of
264267
Nothing ->

src/Formless/Internal/Debounce.purs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ import Effect.Aff.AVar as AVar
1111
import Effect.Aff.Class (class MonadAff)
1212
import Effect.Ref (Ref)
1313
import Effect.Ref as Ref
14-
import Formless.Types.Component (HalogenM)
14+
import Formless.Types.Component (HalogenM, Debouncer)
1515
import Formless.Types.Form (FormField)
16+
import Halogen (ForkId)
1617
import Halogen as H
1718

1819
-- | A helper function to debounce actions on the form and form fields. Implemented
@@ -42,19 +43,19 @@ debounceForm ms pre post last = do
4243
var <- H.liftAff $ AVar.empty
4344
fiber <- mkFiber var
4445

45-
_ <- H.fork do
46-
void $ H.liftAff (AVar.take var)
47-
H.liftEffect $ traverse_ (Ref.write Nothing) dbRef
48-
atomic post (Just last)
46+
forkId <- processAfterDelay var dbRef
4947

50-
H.liftEffect $ for_ dbRef $ Ref.write (Just { var, fiber })
48+
H.liftEffect $ for_ dbRef $ Ref.write (Just { var, fiber, forkId })
5149
atomic pre Nothing
5250

5351
Just db -> do
5452
let var = db.var
53+
forkId' = db.forkId
5554
void $ killFiber' db.fiber
55+
void $ H.kill forkId'
5656
fiber <- mkFiber var
57-
H.liftEffect $ for_ dbRef $ Ref.write (Just { var, fiber })
57+
forkId <- processAfterDelay var dbRef
58+
H.liftEffect $ for_ dbRef $ Ref.write (Just { var, fiber, forkId })
5859

5960
where
6061
mkFiber :: AVar Unit -> HalogenM form st act ps msg m (Fiber Unit)
@@ -68,6 +69,12 @@ debounceForm ms pre post last = do
6869
readRef :: forall x n. MonadAff n => Maybe (Ref (Maybe x)) -> n (Maybe x)
6970
readRef = H.liftEffect <<< map join <<< traverse Ref.read
7071

72+
processAfterDelay :: AVar Unit -> (Maybe (Ref (Maybe Debouncer))) -> HalogenM form st act ps msg m ForkId
73+
processAfterDelay var dbRef = H.fork do
74+
void $ H.liftAff (AVar.take var)
75+
H.liftEffect $ traverse_ (Ref.write Nothing) dbRef
76+
atomic post (Just last)
77+
7178
atomic
7279
:: forall n
7380
. MonadAff n

src/Formless/Internal/Transform.purs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,19 +184,18 @@ unsafeRunValidationVariant
184184
=> form Variant U
185185
-> form Record (Validation form m)
186186
-> form Record FormField
187-
-> m (form Record FormField)
187+
-> m ((form Record FormField) -> (form Record FormField))
188188
unsafeRunValidationVariant var vs rec = rec2
189189
where
190190
label :: String
191191
label = case unsafeCoerce (unwrap var) of
192192
VariantRep x -> x.type
193193

194-
rec2 :: m (form Record FormField)
194+
rec2 :: m ((form Record FormField) -> (form Record FormField))
195195
rec2 = case unsafeGet label (unwrap rec) of
196196
FormField x -> do
197197
res <- runValidation (unsafeGet label $ unwrap vs) rec x.input
198-
let rec' = unsafeSet label (FormField $ x { result = fromEither res }) (unwrap rec)
199-
pure (wrap rec')
198+
pure (\newRec -> wrap $ unsafeSet label (FormField $ x { result = fromEither res }) (unwrap newRec))
200199

201200
-----
202201
-- Classes (Internal)

src/Formless/Types/Component.purs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import Type.Row (type (+))
2020
import Halogen as H
2121
import Halogen.HTML as HH
2222
import Halogen.Query.ChildQuery (ChildQueryBox)
23+
import Halogen.Query.HalogenM (ForkId)
2324

2425
-- | A type representing the various functions that can be provided to extend
2526
-- | the Formless component. Usually only the `render` function is required,
@@ -160,6 +161,7 @@ derive instance newtypeInternalState :: Newtype (InternalState form m) _
160161
type Debouncer =
161162
{ var :: AVar Unit
162163
, fiber :: Fiber Unit
164+
, forkId :: ForkId
163165
}
164166

165167
-- | A type to represent validation status

0 commit comments

Comments
 (0)