Reflex is a class library for writing reactive Perl programs. It provides base classes for reactive objects, and specific subclasses for various tasks.

Why does this Reflex code result in Dynamics firing indefinitely with the same value?

The intent of this small program is to show three buttons, with the third button's label initially being "0" and afterwards being the index of the last-clicked button. For now the number of buttons and the labels of the other buttons are constant.

When I compile this self-contained file with ghcjs and load Main.jsexe/index.html in the browser, I can see the two traceDyns firing in a loop, both always having the value 0. As far as I understand, nothing should happen until a button is clicked, because the _el_clicked feeds the rest of the system.

Also, note that I'm using mapDyn (fst . head . Map.toList) in order to extract the index of the selected button - I'm not sure this is correct, but either way I don't know what causes the infinite looping.

{-# LANGUAGE RecursiveDo #-}

module Main where

import Reflex
import Reflex.Dom

import qualified Data.Map as Map

  :: MonadWidget t m
  => Dynamic t String
  -> m (Event t ())
dynButton s = do
  (e, _) <- el' "button" $ dynText s
  return $ _el_clicked e

-- widget that takes dynamic list of strings
-- and displays a button for each, returning
-- an event of chosen button's index
  :: MonadWidget t m
  => Dynamic t [String]
  -> m (Event t Int)
listChoiceWidget choices = el "div" $ do
  asMap <- mapDyn (Map.fromList . zip [(0::Int)..]) choices
  evs <- listWithKey asMap (\_ s -> dynButton s)
  k <- mapDyn (fst . head . Map.toList) evs
  return $ updated (traceDyn "k" k)

options :: MonadWidget t m => Dynamic t Int -> m (Dynamic t [String])
options foo = do
  mapDyn (\x -> ["a", "b", show x]) foo

main :: IO ()
main = mainWidget $ el "div" $ do
  rec n <- listChoiceWidget o
      o <- options foo
      foo <- holdDyn 0 n
  display (traceDyn "foo" foo)

Source: (StackOverflow)

XhrRequest with reflex/reflex-dom

I want to perform a basic Ajax request, that's all.

I use reflex for the frontend and Scotty for the backend. The Firefox Web Console tells me the request was a success and I see the expected result there. But the website switches from Just "default" to Nothing instead of Just "success!".

Here is a complete minimal example:

import Reflex (holdDyn)
import Reflex.Dom (button, el, mainWidget, display)
import Reflex.Dom.Xhr (performRequestAsync, xhrRequest, decodeXhrResponse)
import Reflex.Class (tag, constant)
import Data.Default (def)

main :: IO ()
main = do
  mainWidget $ el "div" $ do
    buttonEvent <- button "click me"
    let defaultReq = xhrRequest "GET" "mystring" def  --served by Scotty
    asyncEvent <- performRequestAsync (tag (constant defaultReq) buttonEvent)
    buttonDyn <- holdDyn (Just "default") $ fmap decodeXhrResponse asyncEvent
    display buttonDyn

and the Scotty part:

{-# LANGUAGE OverloadedStrings #-}
import Web.Scotty
import Network.Wai.Middleware.Static

main = scotty 3000 $ do
  middleware $ staticPolicy (noDots >-> addBase "/mnt/b/haskell/try-reflex/hello.jsexe")
  get "/" $ do
    file "/mnt/b/haskell/try-reflex/hello.jsexe/index.html"
  get "/mystring" $ html "success!"

Since the debug tools tell me the request was a success, I suspect the error somewhere near decodeXhrResponse but I am a bit lost how I should proceed debugging since it just gets compiled to (unreadable) Javascript.

I used the try-reflex Nix script from GitHub to set up everything and compiled with ghcjs hello.hs in the Nix environment.

Edit: Adding the output of curl:

$ curl -G http://localhost:3000/mystring

Source: (StackOverflow)

What is the proper way in reflex-dom to handle a modal dialog?

I am just starting with the reflex-dom library and I cannot quite figure out the proper and convenient way to work with dialogs.

Showing a dialog generally means adding a few elements to the end of <body> and removing it when the user clicks on some button, backdrop or presses e.g. escape. However doing this from some nested widget means somehow bubbling up the event ('show the dialog') to the top, which could be quite clumsy. Is there any other way to do it nicely? I just had a look at and that seems to use some JS/jQuery hacks.

I can decide not to use modal dialogs (it may not be a bad option after all), but for some things I may really need it.

Source: (StackOverflow)