Core concepts
Attributes & properties
The Attribute type carries everything that can be attached to a DOM element:
data Attribute model action
= Property MisoString Value -- DOM property (key/value)
| ClassList [MisoString] -- CSS class list
| On (model -> Sink action -> ...) -- fully-applied event handler
| OnStatic (StaticPtr (EventHandler model action)) -- static handler, rebuilt on the main thread (dual-thread)
| Styles (Map MisoString MisoString) -- inline style mapIn practice you never construct these directly. Use the smart constructors from Miso.Html.Property, Miso.Html.Event, Miso.Property and Miso.CSS:
H.div_
[ HP.id_ "container" -- textProp "id"
, HP.className "card" -- ClassList
, HP.classList_ [ ("active", isActive) ] -- ClassList, conditional
, HP.disabled_ -- boolProp "disabled" True
, HE.onClick MyAction -- On event handler
, CSS.style_ [ CSS.display "flex" ] -- Styles map
]
[]Custom properties
Use prop (or the typed variants textProp, boolProp, intProp, doubleProp, objectProp) from Miso.Property to set arbitrary DOM properties:
prop "data-index" (42 :: Int) -- sets element.data-index = 42
textProp "placeholder" "Search…" -- sets element.placeholder
boolProp "checked" True -- sets element.checked = trueNote that DOM properties and HTML attributes are distinct. miso tries to set properties on the DOM node object (e.g. node.checked) first, then falls back to setting the HTML attribute (setAttribute("checked", …)). This matches what the browser exposes in JavaScript and avoids common pitfalls with boolean attributes.
Keys
key_ (and its alias keyProp) attaches a reconciliation key to any element. See Keys for details.
data Item = Item { itemId, itemLabel :: MisoString }
H.li_ [ key_ (itemId item) ] [ text (itemLabel item) ]Try it
65% → .bar-ok
data BarModel = BarModel { _pct :: Int }
deriving (Show, Eq)
data BarAction = SetPct MisoString
battery :: Component ctx () BarModel BarAction
battery = component (BarModel 65) update view
where
update (SetPct v) = modify (\m -> m { _pct = fromMisoString v })
view _ () (BarModel p) =
H.div_ []
[ H.div_ [ HP.class_ "bar-track", HP.title_ (ms p <> "%") ] -- textProp "title"
[ H.div_
[ HP.classList_ -- conditional classes
[ ("bar", True)
, ("bar-low", p < 30)
, ("bar-ok", p >= 30 && p < 80)
, ("bar-full", p >= 80)
]
, CSS.style_ -- structured inline style
[ CSS.width (CSS.pct (fromIntegral p))
, CSS.transition_ "width" (CSS.ms 250) "ease-out"
]
] []
]
, H.input_
[ HP.type_ "range", HP.min_ "0", HP.max_ "100"
, HP.value_ (ms p), HE.onInput SetPct
]
, H.p_ [ HP.class_ "muted" ]
[ H.code_ [] [ text (ms p), "% → ." , text klass ] ]
]
where
klass | p < 30 = "bar-low"
| p < 80 = "bar-ok"
| otherwise = "bar-full"