on develop help sign in
Improve efficiency of inputElement for ImmediateDomBuilderT
e2ff6e8Daniel Haraj
src/Reflex/Dom/Builder/Class.hs+14−6
@@ -22,6 +22,7 @@ module Reflex.Dom.Builder.Class
22
22
23import Reflex.Class as Reflex
23import Reflex.Class as Reflex
24import Reflex.Dom.Builder.Class.Events
24import Reflex.Dom.Builder.Class.Events
25+import Reflex.Dom.Builder.Class.TH
25import Reflex.DynamicWriter
26import Reflex.DynamicWriter
26import Reflex.EventWriter
27import Reflex.EventWriter
27import Reflex.PerformEvent.Class
28import Reflex.PerformEvent.Class
@@ -240,7 +241,7 @@ data Placeholder above t
240
241
241data InputElementConfig er t m
242data InputElementConfig er t m
242 = InputElementConfig { _inputElementConfig_initialValue :: Text
243 = InputElementConfig { _inputElementConfig_initialValue :: Text
243− , _inputElementConfig_setValue :: Event t Text
244+ , _inputElementConfig_setValue :: Maybe (Event t Text)
244 , _inputElementConfig_initialChecked :: Bool
245 , _inputElementConfig_initialChecked :: Bool
245 , _inputElementConfig_setChecked :: Event t Bool
246 , _inputElementConfig_setChecked :: Event t Bool
246 , _inputElementConfig_elementConfig :: ElementConfig er t m
247 , _inputElementConfig_elementConfig :: ElementConfig er t m
@@ -250,7 +251,7 @@ instance (Reflex t, er ~ EventResult, DomBuilder t m) => Default (InputElementCo
250 {-# INLINABLE def #-}
251 {-# INLINABLE def #-}
251 def = InputElementConfig
252 def = InputElementConfig
252 { _inputElementConfig_initialValue = ""
253 { _inputElementConfig_initialValue = ""
253− , _inputElementConfig_setValue = never
254+ , _inputElementConfig_setValue = Nothing
254 , _inputElementConfig_initialChecked = False
255 , _inputElementConfig_initialChecked = False
255 , _inputElementConfig_setChecked = never
256 , _inputElementConfig_setChecked = never
256 , _inputElementConfig_elementConfig = def
257 , _inputElementConfig_elementConfig = def
@@ -327,9 +328,8 @@ data SelectElement er d t = SelectElement
327 , _selectElement_raw :: RawSelectElement d
328 , _selectElement_raw :: RawSelectElement d
328 }
329 }
329
330
330−makeLensesFor
331+makeLensesWithoutField "_textNodeConfig_setContents" ''TextNodeConfig
331− [("_textNodeConfig_initialContents", "textNodeConfig_initialContents")]
332+makeLensesWithoutField "_inputElementConfig_setValue" ''InputElementConfig
332− ''TextNodeConfig
333
333
334-- | This lens is technically illegal. The implementation of 'TextNodeConfig' uses a 'Maybe' under the hood for efficiency reasons. However, always interacting with 'TextNodeConfig' via lenses will always behave correctly, and if you pattern match on it, you should always treat 'Nothing' as 'never'.
334-- | This lens is technically illegal. The implementation of 'TextNodeConfig' uses a 'Maybe' under the hood for efficiency reasons. However, always interacting with 'TextNodeConfig' via lenses will always behave correctly, and if you pattern match on it, you should always treat 'Nothing' as 'never'.
335textNodeConfig_setContents :: Reflex t => Lens (TextNodeConfig t) (TextNodeConfig t) (Event t Text) (Event t Text)
335textNodeConfig_setContents :: Reflex t => Lens (TextNodeConfig t) (TextNodeConfig t) (Event t Text) (Event t Text)
@@ -340,10 +340,18 @@ textNodeConfig_setContents =
340 setter t e = t { _textNodeConfig_setContents = Just e }
340 setter t e = t { _textNodeConfig_setContents = Just e }
341 in lens getter setter
341 in lens getter setter
342
342
343+-- | This lens is technically illegal. The implementation of 'InputElementConfig' uses a 'Maybe' under the hood for efficiency reasons. However, always interacting with 'InputElementConfig' via lenses will always behave correctly, and if you pattern match on it, you should always treat 'Nothing' as 'never'.
344+inputElementConfig_setValue :: Reflex t => Lens (InputElementConfig er t m) (InputElementConfig er t m) (Event t Text) (Event t Text)
345+inputElementConfig_setValue =
346+ let getter t = case _inputElementConfig_setValue t of
347+ Nothing -> never
348+ Just e -> e
349+ setter t e = t { _inputElementConfig_setValue = Just e }
350+ in lens getter setter
351+
343concat <$> mapM makeLenses
352concat <$> mapM makeLenses
344 [ ''ElementConfig
353 [ ''ElementConfig
345 , ''PlaceholderConfig
354 , ''PlaceholderConfig
346− , ''InputElementConfig
347 , ''TextAreaElementConfig
355 , ''TextAreaElementConfig
348 , ''SelectElementConfig
356 , ''SelectElementConfig
349 , ''RawElementConfig
357 , ''RawElementConfig
src/Reflex/Dom/Builder/Class/TH.hsnew file+12
@@ -0,0 +1,12 @@
1+module Reflex.Dom.Builder.Class.TH where
2+
3+import Control.Lens
4+import Language.Haskell.TH.Syntax (Name, nameBase)
5+import Language.Haskell.TH.Lib (DecsQ)
6+
7+namer :: String -> Name -> [Name] -> Name -> [DefName]
8+namer s n ks t | s == nameBase t = []
9+ | otherwise = underscoreNoPrefixNamer n ks t
10+
11+makeLensesWithoutField :: String -> Name -> DecsQ
12+makeLensesWithoutField s = makeLensesWith (lensRules & lensField .~ namer s)
src/Reflex/Dom/Builder/Immediate.hs+5−3
@@ -313,9 +313,11 @@ instance SupportsImmediateDomBuilder t m => DomBuilder t (ImmediateDomBuilderT t
313 Just v0 <- Input.getValue domInputElement
313 Just v0 <- Input.getValue domInputElement
314 let getMyValue = fromMaybe "" <$> Input.getValue domInputElement
314 let getMyValue = fromMaybe "" <$> Input.getValue domInputElement
315 valueChangedByUI <- performEvent $ getMyValue <$ Reflex.select (_element_events e) (WrapArg Input)
315 valueChangedByUI <- performEvent $ getMyValue <$ Reflex.select (_element_events e) (WrapArg Input)
316− valueChangedBySetValue <- performEvent $ ffor (cfg ^. inputElementConfig_setValue) $ \v' -> do
316+ valueChangedBySetValue <- case _inputElementConfig_setValue cfg of
317+ Nothing -> return never
318+ Just eSetValue -> performEvent $ ffor eSetValue $ \v' -> do
317− Input.setValue domInputElement $ Just v'
319+ Input.setValue domInputElement $ Just v'
318− getMyValue -- We get the value after setting it in case the browser has mucked with it somehow
320+ getMyValue -- We get the value after setting it in case the browser has mucked with it somehow
319 v <- holdDyn v0 $ leftmost
321 v <- holdDyn v0 $ leftmost
320 [ valueChangedBySetValue
322 [ valueChangedBySetValue
321 , valueChangedByUI
323 , valueChangedByUI