`on UI.valueChange` not triggered until ESC pressed
jerbaroo opened this issue · comments
Here is the code for the problem described below.
main :: IO ()
main = do
startGUI defaultConfig setup
setup :: Window -> UI ()
setup window = do
(event, handler) <- liftIO $ newEvent
behavior <- stepper "No file selected." event
text <- UI.div # sink UI.text behavior
input <- UI.input # set UI.type_ "file"
-- input <- UI.button # set UI.text "file"
getBody window #+ map element [text, input]
on UI.valueChange input $ const $ do
liftIO $ handler "File selected."
Problem
- Initially the
text
of thediv
is"No file selected."
. - Click the
input
and select a file. - Observe the
text
of thediv
not change. - Press the ESC key.
- Observe the
text
of thediv
change to"File selected."
. (Chrome only) - Use a
button
instead ofinput
, by using the commented line, and the problem is the same.
Reproduce
git clone https://github.com/barischj/threepenny-slow-valuechange
cd threepenny-slow-valuechange
stack setup && stack build && stack exec threepenny-slow-frp-exe
- Open browser to localhost:8023 and follow problem steps.
System
- OS X 10.11.6
- Chrome 56.0.2924.87
Additional notes:
- On Firefox 51.0.1 and Safari 10.0.3 the
text
of thediv
won't update even after pressing ESC.
Fix
A fix for this was not to use UI.valueChange
which uses the DOM keydown
event, but instead use a new event function which uses the DOM change
event:
...
on change input $ const $ do
liftIO $ handler "File selected."
-- |change event.
change :: Element -> Event ()
change = void . domEvent "change"
The documentation for the DOM change
event is very similar to that of UI.valueChange
:
UI.valueChange
:
Event that occurs when the user changes the value of the input element.
change
:
The change event is fired for <input>, <select>, and <textarea> elements when a change to the element's value is committed by the user.
The main reason why I used the keypress
event was that this makes sure that the user is the one who did the change. (This is relevant for a smooth FRP experience.) The documentation you mention indicates that the change
event ensures the same thing, and I'm inclined to use it in the implementation of valueChange
.
However: Do browser really follow this specification, or do they also emit a change
event when the contents of the DOM element was changed programmatically, e.g. with input.val('foo')
(in jQuery notation)? The latter would be undesirable.
I ran into this (or similar) problem when I wanted to use sliders (input type = range) as input.
https://gitlab.imn.htwk-leipzig.de/waldmann/matrix-game/blob/master/src/Main.hs#L101
@maweki solved it with onDomEvent "input"
. This is currently is not exported?