Any chance of an example showing how to debounce rendering an input
jerbaroo opened this issue · comments
Love the library, chose it for a recent project I am working on. Struggling to figure some things out, but getting there.
I am a bit stumped on how to debounce the rendering of error text for this input component. The code should be fairly illustrative on what I am trying to accomplish:
input _ initialMay onKeyup = Deku.do
-- We save the raw input to calculate error messages.
setValueMay /\ valueMay <- useState initialMay
D.div
[ ]
[ D.input
( [ DA.value $ valueMay <#> maybe "" repr
, DL.keyup_ $ \event -> Event.withTargetValue (toEvent event) \s -> do
setValueMay $ Just s
onKeyup s -- Should be executed without any debounce delay.
]
<> flip (maybe []) initialMay \v -> [ DA.value_ v ]
)
[]
, D.div
[ DA.klass_ "input-error" ]
[ valueMay <#~> case _ of
-- Should only be rendered after a debounce period.
Nothing -> text_ ""
Just value -> case parse value of
Right (_ :: a) -> text_ ""
Left error ->
-- Only show the error if input is non-empty.
text_ $ if String.length value == 0 then "" else error
]
]
Yes, I can put this together & thanks for requesting it!
Thanks for your patience: deku went through a big rewrite for this sort of thing recently & I can now report how to go about this.
You'll want to create a custom with
combinator, ie withDebounce
. You can build it off of withDelay
(https://github.com/mikesol/purescript-hyrule/blob/main/src/FRP/Event/Time.purs) and then do ie under Op (withDebounce nMilliseconds) setValueMay $ Just s
. The hyrule tests use this pattern quite a bit: https://github.com/mikesol/purescript-hyrule/blob/main/test/Main.purs, check withTime
in there for example.
It's a fun little exercise to create a withDebounce
from withDelay
. GIve it a try! If it's too challenging, let me know and I can help out. Here are a couple hints.
- The signature will be
withDebounce :: forall a. Int -> Op (Effect Unit) a -> Op (Effect Unit) a
. - It will use
withDelay
, so some intermediary function will need to have the signature:Op (Effect Unit) a -> Op (Effect Unit) (Either TimeoutId (Tuple TimeoutId a))
. This feels a little backwards when you look at it because it looks like it's producing the type ofwithDelay
but it's actually consuming it. This is one of the neat things aboutOp
.