hansroland / reflex-dom-inbits

A tutorial for reflex-dom with small code bits
BSD 3-Clause "New" or "Revised" License
116 stars 46 forks source link

Suggestions about tracing and empty attributes #13

Closed gspia closed 7 years ago

gspia commented 7 years ago

After first reading and the first trials, I think that explaining tracing and debugging basics would make a nice addition to your tutorial. And similarly for the attributes. How to make a elDynAttr or elDynAttr' with empty attributes or is there another function to use in those situations? In the following I was able to get the program compile with a clumsy trick. (The Bool is not used at the moment.)

The following is somehow made up button that can dynamically change its label and output to browser console. I used ghci to find out the type for the function and don't know if there is a shorter synonym for that.

My first thought was to put tracing in places, where I call toggleButton, but couldn't do that. Do you know if there is a way to output to browser console in main?

I looked up at some of the libs/project listed at the end of tutorial for examples on how to use trace. Found some, but the situations were much more complex than the examples in this tutorial, which is the reason it wasn't immediately obvious, how to use tracing.

-- toggleButton :: MonadWidget t m
--             => Dynamic t Bool -- ^ enable or disable button
--             -> Dynamic t T.Text  -- ^ Label
--             -> m (Event t ())
toggleButton :: (Reflex t, PostBuild t1 m, DomBuilder t1 m,
      HasDomEvent t (Element EventResult (DomBuilderSpace m) t1) 'ClickTag)
  => Dynamic t1 a -> Dynamic t1 T.Text -> m (Event t ())
toggleButton b label = do
  -- let attrs = ffor b $ \e -> monoidGuard (not e) $ "disabled" =: "disabled"
  let attrs = ffor b $ \e -> mempty
  (btn, _) <- elDynAttr' "button" attrs $ dynText label
  -- (btn, _) <- elDynAttr' "button" empty $ dynText label
  -- btn <- elDynHtml' "button" $ dynText label
  -- (btn, _) <- elDyn' "button" $ text label
  -- pure $ domEvent Click (traceEvent "hmm" btn)
  pure $ traceEvent "hmm" $ domEvent Click btn
  -- pure $ domEvent Click btn
hansroland commented 7 years ago

Tracing If you look up the function traceEvent in https://github.com/reflex-frp/reflex/blob/develop/src/Reflex/Class.hs you see the following:

-- Note: As with Debug.Trace.trace, the message will only be printed if the
-- 'Event' is actually used.
traceEvent :: (Reflex t, Show a) => String -> Event t a -> Event t a

So traceEvent takes a String and an Event and returns a new Event. And the comment says, that the debug message will only be printed if the 'Event' is actually used. It doesn't say it explicitely, but it means, the new Event, returned by the function traceEvent has to be used!

Here I'm extending a code snippet from the example src/radio02.hs from the tutorial:

-- | Helper function to create a radio button
radioBtn :: (Eq a, Show a, MonadWidget t m) => T.Text -> T.Text -> a -> Dynamic t ( Map.Map T.Text T.Text)-> m (Event t a)
radioBtn label group rid dynAttrs = do
    el "br" blank 
    ev <- elDynAttr "label" dynAttrs $ do
        (rb1, _) <- elAttr' "input" ("name" =: group <> "type" =: "radio" <> "value" =: T.pack (show rid))  blank
        text label
        return $ domEvent Click rb1
    let evT = traceEvent "hmm" ev        -- ADDED LINE
    return $ rid <$ evT                  -- MODIFIED LINE:  evT instead of ev

In the second last line the function traceEvent returns a new event evT. This new event is used in the last line and shows up in the browser-console (I tested with Firefox and Chrome). If you click multiple times, both browsers will not repeat the line but increment a number in a colored circle. (Firefox at the right end of the line, Chrome at the left).

If you change the last line back to return $ rid <$ ev the event evT will no longer be used/consumed, hence according to the program comment there is no output on the browser-console!

Empty Attributes: I don't really understand your question. What should be the difference to the example src/button01.hs? If you have no attributes, you can just use the el or el' functions.

Extending the tutorial If I find a really good example, maybe I'll extend the tutorial.

gspia commented 7 years ago

Thanks for your detailed answer! And thanks again for the tutorial! This really helps!

About those empty attributes: I tried with el' and it works. Somehow I thought earlier that el' cannot be used with dynamic text dynText but that was clearly wrong.

In the tutorial, there is a section Function: elDynAttr and its first sentences are:

All the above functions allow us to define static DOM elements. But you cannot change them while the program is running!

And earlier things include el and el' (el' seems to come later but there it is shown as a way to see the internals). Does the tutorial refer to static attributes but not saying that the second parameter has to be something static, too?

Maybe a small change to the two sentences? (Now I cannot suggest a change since I'm not sure what is static in there.)

Earlier at the introduction to Function el, there is a sentence

The second parameter is either the text of the element or a child element.

Does this mean also that the child element can be anything producing html in the end? Static as well dynamic? If so, maybe some small addition to the sentence or one additional sentence like ".. is either text of the element (e.g. text "my txt") or a child element (e.g. dynText aVariable, see below)." And then it could have a link to the example showing how to use el' without attributes with dynText.

hansroland commented 7 years ago

Static vs Dynamic

I no longer write about static or dynamic DOM elements but about static or dynamic attributes. So, I have changed:

All the above functions allow us to define static DOM elements. But you cannot change them while the program is running! With the function elDynAttr, as the name says, you can specify attributes, that change during program execution.

to:

All the above functions allow us to define DOM elements with static attributes. But you cannot change the attributes while the program is running! With the function elDynAttr, as the name says, you can specify dynamic attributes, that change during program execution.

I hope this makes it clearer. So, yes, a parent with static attributes may have children with dynamic attributes. In real life there are a lot of div elements with no attributes or static attributes, that have children with dynamic attributes.

And yes, it means that a child can be anything that produces valid html in the end.

hansroland commented 7 years ago

@gspia I added a new section about tracing. Thanks for helping to improve this tutorial! If you don't mind, I'll close this issue.

gspia commented 7 years ago

That's ok and thanks for the tutorial! (I can close this one too.)