Search code examples
haskellthreepenny-gui

using threepenny-gui/reactive in client/server programming


I am trying to figure out how to use Haskell threepenny-gui with its reactive functionality to write a program that lets

  • the user select an item from a listBox
  • send the selection to an external server
  • get back a list of results from the server
  • populate the listBox with the results
  • repeat

It seems I will need to use Handler, newEvent and register to do the above. If someone could point me to some existing code that does something like the above that would be great.

The closest I have found is GameThing.hs in the threepenny-gui samples directory (but it doesn't use register).

UPDATE:

I am asking whether I should be using Handler, newEvent and register --- and, if so, some clarification or example of those functions.

Also, to be clear, the big picture is:

browser  --> threepenny-gui (on localhost) --> backend server (anywhere on network)
         <--                               <--

In other words, I need to do some IO (based on user selection) then display the results of that IO.

UPDATE: here is my solution (based on @Taldykin's response): https://github.com/haroldcarr/rdf-triple-browser/tree/master/haskell/src


Solution

  • enter image description here

    Here is a piece of code. I will add description a bit later.

    {-# LANGUAGE LambdaCase #-}
    import Graphics.UI.Threepenny as UI
    
    
    main :: IO ()
    main = do
      (evFillList, doFillList) <- newEvent
      initialList <- valuesSupply ""
      behFillList <- stepper initialList evFillList
    
      startGUI defaultConfig $ \win -> do
        list <- ul
        sel <- listBox
            behFillList
            (pure Nothing)
            (pure $ \it -> UI.span # set text it)
    
        getBody win #+ [grid [[element list, element sel]]]
        setFocus $ getElement sel
    
        on selectionChange (getElement sel) $ \case
          Nothing -> return ()
          Just ix -> do
            items <- currentValue behFillList
            let it = items !! ix
            liftIO $ valuesSupply it >>= doFillList
            element list #+ [li # set html it]
            setFocus $ getElement sel
    
    
    valuesSupply :: String -> IO [String]
    valuesSupply x = return [x ++ show i | i <- [0..9]]