我想要做的是设置显示焦点时的详细信息的字段,但是当它们不在时会显示摘要。例如。
A)。当它失去焦点(变得模糊?)时,我将值保存在(状态?)Map中,然后将值更改为旧值的函数(即汇总值)
B)。当它获得焦点时 - 我将汇总值替换为我在Map
中保存的旧值我无法弄清楚如何做到这一点,但我想我可能需要一个状态monad和UI monad。我的尝试是:
renderField :: Map->Int->UI (Element, Map)
renderField vs ix = do
input <- UI.input
on UI.blur input $ \_ -> void $ do
fieldValue <- get value input
let newVs = insert ix fieldValue vs
return input # set UI.value (calcNewValue fieldValue)
on UI.focus input $ \_ -> void $ do
let savedValue = findWithDefault "" ix vs
return input # set UI.value savedValue
return (input, newVs)
但我无法让这张地图发挥作用 - 因为它需要跟踪所有的电话......我想它应该是State monad还是什么?
感谢。
<磷>氮答案 0 :(得分:2)
的确,你需要跟踪状态。
但是,通常的模式s -> (a,s)
(状态monad)在这里不适用,因为您正在使用回调函数。对于这些,您需要一个不同的模式。
在传统的命令式样式中,人们会在这里使用一个可变变量,例如IORef
。请注意,不再需要跟踪索引 - 您可以将IORef
视为大型可变地图中的索引。
renderField :: UI Element
renderField = do
input <- UI.input
state <- liftIO $ newIORef
on UI.blur input $ \_ -> do
fieldValue <- get value input
liftIO $ writeIORef state fieldValue
element input # set UI.value (calcNewValue fieldValue)
on UI.focus input $ \_ -> do
savedValue <- liftIO $ readIORef state
element input # set UI.value savedValue
return input
或者,您也可以在Threepenny中使用功能反应式编程(FRP)。请注意,API仍有些初步,以下代码特定于threepenny-gui
版本0.4.*
:
renderField :: UI Element
renderField = do
input <- UI.input
bValueUser <- stepper "" $ UI.valueChange input
bState <- stepper "" $ bValueUser <@ UI.blur input
bValue <- stepper "" $ fmap head $ unions
[ (calcNewValue <$> bValueUser) <@ UI.blur input
, bState <@ UI.focus input
]
element input # sink UI.value bValue
同样,这段代码中还有一些细微之处和瑕疵,但这是我想要了解的一般方向。有关FRP及其如何应用于GUI开发的一些初步信息可以在{{3 }}
我建议您在需要快速完成任务时使用熟悉的解决方案(IORef
),并在有足够的空闲时间时探索FRP解决方案。 documentation主要使用FRP样式。
(披露:我是Threepenny的作者。)