So I have a simple example layout with a listbox, a button and a textarea, where clicking the button changes the text in the textarea:
import Control.Applicative
import Control.Monad
import Data.Maybe
import qualified Graphics.UI.Threepenny as UI
import Graphics.UI.Threepenny.Core
main :: IO ()
main = startGUI defaultConfig setup
setup :: Window -> UI ()
setup w = do
return w # set UI.title "Simple example"
listBox <- UI.listBox (pure ["First", "Second"]) (pure Nothing) ((UI.string .) <$> (pure id))
button <- UI.button # set UI.text "Button"
display <- UI.textarea # set UI.text "Initial value"
element listBox # set (attr "size") "10"
getBody w #+ [element listBox, element button, element display]
on UI.click button $ const $ do
element display # set UI.text "new text"
What I wanted to do is have the change be dependent on the listbox selection (for example have the "new text"
be "First"
or "Second"
based on the selection).
I can quite easily get the selection by combining userSelection
and facts
as
facts . userSelection :: ListBox a -> Behavior (Maybe a)
but because setting the value for the textarea is done with
set text :: String -> UI Element -> UI Element
I don't know how to work around the fact that the selection is a Behavior
.
All this seems a bit unidiomatic to me and I was wondering what would be the correct way to do this. Maybe I should do something already when the listbox selection is done or changed and not only when the button is pressed.
First of all, there was a regression which affected the code here. That issue is now solved. Threepenny 0.6.0.3 has a temporary fix, and the definitive one will be included in the release after that.
The code in the pastebin you provided is almost correct. The only needed change is that you don't need to use
sink
within the button click callback - in your case,sink
should establish a permanent connection between a behavior and the content of the text area, with the behavior value changing in response to the button click events.For the sake of completeness, here is a full solution:
The two key things to take away are:
Behavior (Maybe a)
argument tolistBox
does not set just the initial selected value, but determines the evolution of the value throughout the lifetime of the application. In this example,facts $ UI.userSelection listBox
is justbSelected
, as can be verified through the source code of theWidgets
module.(<@)
(or<@>
if the event carries data you wish to make use of).