on develop help sign in
selectElement implementation
0f43aa7Tom Smalley
reflex-dom-core/src/Reflex/Dom/Builder/Hydration.hs+50−21
@@ -768,31 +768,60 @@ instance (SupportsHydrationDomBuilder t m) => DomBuilder t (HydrationDomBuilderT
768
768
769 {-# INLINABLE selectElement #-}
769 {-# INLINABLE selectElement #-}
770 selectElement cfg child = do
770 selectElement cfg child = do
771− ((e, result), _domElement') <- makeElement "select" (cfg ^. selectElementConfig_elementConfig) child
771+ ((e, result), domElementRef) <- makeElement "select" (cfg ^. selectElementConfig_elementConfig) child
772− let domElement = undefined :: DOM.HTMLSelectElement
772+
773− let domSelectElement = uncheckedCastTo DOM.HTMLSelectElement domElement
773+ (valueChangedByUI, triggerChangeByUI) <- newTriggerEvent
774− Select.setValue domSelectElement $ cfg ^. selectElementConfig_initialValue
774+ (valueChangedBySetValue, triggerChangeBySetValue) <- newTriggerEvent
775− v0 <- Select.getValue domSelectElement
775+
776− let getMyValue = Select.getValue domSelectElement
776+ (focusChange, triggerFocusChange) <- newTriggerEvent
777− valueChangedByUI <- requestDomAction $ liftJSM getMyValue <$ Reflex.select (_element_events e) (WrapArg Change)
777+
778+ doc <- askDocument
779+
780+ -- Expected initial value from config
781+ let v0 = _selectElementConfig_initialValue cfg
782+
783+ addHydrationStep $ do
784+ domElement <- liftIO $ readIORef domElementRef
785+ let domSelectElement = uncheckedCastTo DOM.HTMLSelectElement domElement
786+ getValue = Select.getValue domSelectElement
787+
788+ -- The browser might have messed with the value, or the user could have
789+ -- altered it before activation, so we set it if it isn't what we expect
790+ liftJSM getValue >>= \v0' -> do
791+ when (v0' /= v0) $ liftIO $ triggerChangeByUI v0'
792+
793+ -- Watch for user interaction and trigger event accordingly
794+ requestDomAction_ $ (liftJSM getValue >>= liftIO . triggerChangeByUI) <$ Reflex.select (_element_events e) (WrapArg Change)
795+
778− valueChangedBySetValue <- case _selectElementConfig_setValue cfg of
796+ for_ (_selectElementConfig_setValue cfg) $ \eSetValue ->
779− Nothing -> return never
780− Just eSetValue -> requestDomAction $ ffor eSetValue $ \v' -> do
797+ requestDomAction_ $ ffor eSetValue $ \v' -> do
781− Select.setValue domSelectElement v'
798+ Select.setValue domSelectElement v'
782− getMyValue -- We get the value after setting it in case the browser has mucked with it somehow
799+ v <- getValue -- We get the value after setting it in case the browser has mucked with it somehow
800+ liftIO $ triggerChangeBySetValue v
801+
802+ let focusChange' = leftmost
803+ [ False <$ Reflex.select (_element_events e) (WrapArg Blur)
804+ , True <$ Reflex.select (_element_events e) (WrapArg Focus)
805+ ]
806+ liftIO . triggerFocusChange =<< Node.isSameNode (toNode domElement) . fmap toNode =<< Document.getActiveElement doc
807+ requestDomAction_ $ liftIO . triggerFocusChange <$> focusChange'
808+
809+ let initialFocus = False -- Assume it isn't focused, but we update the actual focus state at switchover
810+ hasFocus <- holdUniqDyn =<< holdDyn initialFocus focusChange
811+
783 v <- holdDyn v0 $ leftmost
812 v <- holdDyn v0 $ leftmost
784 [ valueChangedBySetValue
813 [ valueChangedBySetValue
785 , valueChangedByUI
814 , valueChangedByUI
786 ]
815 ]
787− hasFocus <- mkHasFocus e
816+
788− let wrapped = SelectElement
817+ return $ flip (,) result $ SelectElement
789− { _selectElement_value = v
818+ { _selectElement_value = v
790− , _selectElement_change = valueChangedByUI
819+ , _selectElement_change = valueChangedByUI
791− , _selectElement_hasFocus = hasFocus
820+ , _selectElement_hasFocus = hasFocus
792− , _selectElement_element = e
821+ , _selectElement_element = e
793− , _selectElement_raw = domSelectElement
822+ , _selectElement_raw = undefined -- TODO domSelectElement
794− }
823+ }
795− return (wrapped, result)
824+
796 placeRawElement _ = return () -- append . toNode
825 placeRawElement _ = return () -- append . toNode
797 wrapRawElement e _ = return $ Element (EventSelector $ const never) e -- TODO
826 wrapRawElement e _ = return $ Element (EventSelector $ const never) e -- TODO
798
827