on develop help sign in
Implement textarea, fix textarea tests
d8ef9ffTom Smalley
reflex-dom-core/src/Reflex/Dom/Builder/Hydration.hs+47−19
@@ -653,9 +653,8 @@ instance (SupportsHydrationDomBuilder t m) => DomBuilder t (HydrationDomBuilderT
653 -- Watch for user interaction and trigger event accordingly
653 -- Watch for user interaction and trigger event accordingly
654 requestDomAction_ $ (liftJSM getValue >>= liftIO . triggerChangeByUI) <$ Reflex.select (_element_events e) (WrapArg Input)
654 requestDomAction_ $ (liftJSM getValue >>= liftIO . triggerChangeByUI) <$ Reflex.select (_element_events e) (WrapArg Input)
655
655
656− case _inputElementConfig_setValue cfg of
656+ for_ (_inputElementConfig_setValue cfg) $ \eSetValue ->
657− Nothing -> pure ()
658− Just eSetValue -> requestDomAction_ $ ffor eSetValue $ \v' -> do
657+ requestDomAction_ $ ffor eSetValue $ \v' -> do
659 Input.setValue domInputElement v'
658 Input.setValue domInputElement v'
660 v <- getValue -- We get the value after setting it in case the browser has mucked with it somehow
659 v <- getValue -- We get the value after setting it in case the browser has mucked with it somehow
661 liftIO $ triggerChangeBySetValue v
660 liftIO $ triggerChangeBySetValue v
@@ -691,7 +690,7 @@ instance (SupportsHydrationDomBuilder t m) => DomBuilder t (HydrationDomBuilderT
691 checked <- holdUniqDyn checked'
690 checked <- holdUniqDyn checked'
692
691
693 let initialFocus = False -- Assume it isn't focused, but we update the actual focus state at switchover
692 let initialFocus = False -- Assume it isn't focused, but we update the actual focus state at switchover
694− hasFocus <- holdDyn initialFocus focusChange
693+ hasFocus <- holdUniqDyn =<< holdDyn initialFocus focusChange
695
694
696 v <- holdDyn v0 $ leftmost
695 v <- holdDyn v0 $ leftmost
697 [ valueChangedBySetValue
696 [ valueChangedBySetValue
@@ -712,30 +711,59 @@ instance (SupportsHydrationDomBuilder t m) => DomBuilder t (HydrationDomBuilderT
712 }
711 }
713
712
714 {-# INLINABLE textAreaElement #-}
713 {-# INLINABLE textAreaElement #-}
715− textAreaElement cfg = do --TODO
714+ textAreaElement cfg = do
716− ((e, _), _domElement') <- makeElement "textarea" (cfg ^. textAreaElementConfig_elementConfig) $ return ()
715+ ((e, _), domElementRef) <- makeElement "textarea" (cfg ^. textAreaElementConfig_elementConfig) $ return ()
717− let domElement = undefined :: DOM.HTMLTextAreaElement
716+
718− let domTextAreaElement = uncheckedCastTo DOM.HTMLTextAreaElement domElement
717+ (valueChangedByUI, triggerChangeByUI) <- newTriggerEvent
719− TextArea.setValue domTextAreaElement $ cfg ^. textAreaElementConfig_initialValue
718+ (valueChangedBySetValue, triggerChangeBySetValue) <- newTriggerEvent
720− v0 <- TextArea.getValue domTextAreaElement
719+
721− let getMyValue = TextArea.getValue domTextAreaElement
720+ (focusChange, triggerFocusChange) <- newTriggerEvent
722− valueChangedByUI <- requestDomAction $ liftJSM getMyValue <$ Reflex.select (_element_events e) (WrapArg Input)
721+
722+ doc <- askDocument
723+
724+ -- Expected initial value from config
725+ let v0 = _textAreaElementConfig_initialValue cfg
726+
727+ addHydrationStep $ do
728+ domElement <- liftIO $ readIORef domElementRef
729+ let domTextAreaElement = uncheckedCastTo DOM.HTMLTextAreaElement domElement
730+ getValue = TextArea.getValue domTextAreaElement
731+
732+ -- The browser might have messed with the value, or the user could have
733+ -- altered it before activation, so we set it if it isn't what we expect
734+ liftJSM getValue >>= \v0' -> do
735+ when (v0' /= v0) $ liftIO $ triggerChangeByUI v0'
736+
737+ -- Watch for user interaction and trigger event accordingly
738+ requestDomAction_ $ (liftJSM getValue >>= liftIO . triggerChangeByUI) <$ Reflex.select (_element_events e) (WrapArg Input)
739+
723− valueChangedBySetValue <- case _textAreaElementConfig_setValue cfg of
740+ for_ (_textAreaElementConfig_setValue cfg) $ \eSetValue ->
724− Nothing -> return never
725− Just eSetValue -> requestDomAction $ ffor eSetValue $ \v' -> do
741+ requestDomAction_ $ ffor eSetValue $ \v' -> do
726− TextArea.setValue domTextAreaElement v'
742+ TextArea.setValue domTextAreaElement v'
727− getMyValue -- We get the value after setting it in case the browser has mucked with it somehow
743+ v <- getValue -- We get the value after setting it in case the browser has mucked with it somehow
744+ liftIO $ triggerChangeBySetValue v
745+
746+ let focusChange' = leftmost
747+ [ False <$ Reflex.select (_element_events e) (WrapArg Blur)
748+ , True <$ Reflex.select (_element_events e) (WrapArg Focus)
749+ ]
750+ liftIO . triggerFocusChange =<< Node.isSameNode (toNode domElement) . fmap toNode =<< Document.getActiveElement doc
751+ requestDomAction_ $ liftIO . triggerFocusChange <$> focusChange'
752+
753+ let initialFocus = False -- Assume it isn't focused, but we update the actual focus state at switchover
754+ hasFocus <- holdUniqDyn =<< holdDyn initialFocus focusChange
755+
728 v <- holdDyn v0 $ leftmost
756 v <- holdDyn v0 $ leftmost
729 [ valueChangedBySetValue
757 [ valueChangedBySetValue
730 , valueChangedByUI
758 , valueChangedByUI
731 ]
759 ]
732− hasFocus <- mkHasFocus e
760+
733 return $ TextAreaElement
761 return $ TextAreaElement
734 { _textAreaElement_value = v
762 { _textAreaElement_value = v
735 , _textAreaElement_input = valueChangedByUI
763 , _textAreaElement_input = valueChangedByUI
736 , _textAreaElement_hasFocus = hasFocus
764 , _textAreaElement_hasFocus = hasFocus
737 , _textAreaElement_element = e
765 , _textAreaElement_element = e
738− , _textAreaElement_raw = domTextAreaElement
766+ , _textAreaElement_raw = undefined -- TODO domTextAreaElement
739 }
767 }
740
768
741 {-# INLINABLE selectElement #-}
769 {-# INLINABLE selectElement #-}
reflex-dom-core/test/hydration.hs+8−8
@@ -438,7 +438,7 @@ main = hspec $ parallel $ do
438 inputRef <- newIORef ""
438 inputRef <- newIORef ""
439 testWidget'
439 testWidget'
440 (do
440 (do
441− e <- WD.findElem $ WD.ByTag "input"
441+ e <- WD.findElem $ WD.ByTag "textarea"
442 WD.sendKeys "hello world" e
442 WD.sendKeys "hello world" e
443 pure e)
443 pure e)
444 (\e -> do
444 (\e -> do
@@ -454,7 +454,7 @@ main = hspec $ parallel $ do
454 it "captures user input after switchover" $ do
454 it "captures user input after switchover" $ do
455 inputRef <- newIORef ""
455 inputRef <- newIORef ""
456 let checkValue = do
456 let checkValue = do
457− WD.sendKeys "hello world" <=< WD.findElem $ WD.ByTag "input"
457+ WD.sendKeys "hello world" <=< WD.findElem $ WD.ByTag "textarea"
458 WD.click <=< WD.findElem $ WD.ByTag "button"
458 WD.click <=< WD.findElem $ WD.ByTag "button"
459 input <- liftIO $ readIORef inputRef
459 input <- liftIO $ readIORef inputRef
460 liftIO $ input `shouldBe` "hello world"
460 liftIO $ input `shouldBe` "hello world"
@@ -466,7 +466,7 @@ main = hspec $ parallel $ do
466 focusRef <- newIORef False
466 focusRef <- newIORef False
467 let checkValue = do
467 let checkValue = do
468 liftIO $ readIORef focusRef >>= flip shouldBe False
468 liftIO $ readIORef focusRef >>= flip shouldBe False
469− e <- WD.findElem $ WD.ByTag "input"
469+ e <- WD.findElem $ WD.ByTag "textarea"
470 WD.click e
470 WD.click e
471 liftIO $ threadDelay 100000
471 liftIO $ threadDelay 100000
472 liftIO $ readIORef focusRef >>= flip shouldBe True
472 liftIO $ readIORef focusRef >>= flip shouldBe True
@@ -476,7 +476,7 @@ main = hspec $ parallel $ do
476 it "sets focus when focus occurs before hydration" $ do
476 it "sets focus when focus occurs before hydration" $ do
477 focusRef <- newIORef False
477 focusRef <- newIORef False
478 let setup = do
478 let setup = do
479− e <- WD.findElem $ WD.ByTag "input"
479+ e <- WD.findElem $ WD.ByTag "textarea"
480 WD.click e
480 WD.click e
481 hasFocus <- (== e) <$> WD.activeElem
481 hasFocus <- (== e) <$> WD.activeElem
482 liftIO $ do
482 liftIO $ do
@@ -493,7 +493,7 @@ main = hspec $ parallel $ do
493 let checkValue = do
493 let checkValue = do
494 liftIO $ readIORef valueByUIRef >>= flip shouldBe ""
494 liftIO $ readIORef valueByUIRef >>= flip shouldBe ""
495 liftIO $ readIORef valueRef >>= flip shouldBe ""
495 liftIO $ readIORef valueRef >>= flip shouldBe ""
496− e <- WD.findElem $ WD.ByTag "input"
496+ e <- WD.findElem $ WD.ByTag "textarea"
497 WD.sendKeys "hello" e
497 WD.sendKeys "hello" e
498 liftIO $ do
498 liftIO $ do
499 threadDelay 100000
499 threadDelay 100000
@@ -515,7 +515,7 @@ main = hspec $ parallel $ do
515 it "captures user input after switchover" $ do
515 it "captures user input after switchover" $ do
516 inputRef :: IORef Text <- newIORef ""
516 inputRef :: IORef Text <- newIORef ""
517 let checkValue = do
517 let checkValue = do
518− WD.sendKeys "hello world" <=< WD.findElem $ WD.ByTag "input"
518+ WD.sendKeys "hello world" <=< WD.findElem $ WD.ByTag "textarea"
519 WD.click <=< WD.findElem $ WD.ByTag "button"
519 WD.click <=< WD.findElem $ WD.ByTag "button"
520 input <- liftIO $ readIORef inputRef
520 input <- liftIO $ readIORef inputRef
521 liftIO $ input `shouldBe` "hello world"
521 liftIO $ input `shouldBe` "hello world"
@@ -527,7 +527,7 @@ main = hspec $ parallel $ do
527 focusRef <- newIORef False
527 focusRef <- newIORef False
528 let checkValue = do
528 let checkValue = do
529 liftIO $ readIORef focusRef >>= flip shouldBe False
529 liftIO $ readIORef focusRef >>= flip shouldBe False
530− e <- WD.findElem $ WD.ByTag "input"
530+ e <- WD.findElem $ WD.ByTag "textarea"
531 WD.click e
531 WD.click e
532 liftIO $ threadDelay 100000
532 liftIO $ threadDelay 100000
533 liftIO $ readIORef focusRef >>= flip shouldBe True
533 liftIO $ readIORef focusRef >>= flip shouldBe True
@@ -541,7 +541,7 @@ main = hspec $ parallel $ do
541 let checkValue = do
541 let checkValue = do
542 liftIO $ readIORef valueByUIRef >>= flip shouldBe ""
542 liftIO $ readIORef valueByUIRef >>= flip shouldBe ""
543 liftIO $ readIORef valueRef >>= flip shouldBe ""
543 liftIO $ readIORef valueRef >>= flip shouldBe ""
544− e <- WD.findElem $ WD.ByTag "input"
544+ e <- WD.findElem $ WD.ByTag "textarea"
545 WD.sendKeys "hello" e
545 WD.sendKeys "hello" e
546 liftIO $ do
546 liftIO $ do
547 threadDelay 100000
547 threadDelay 100000