Core concepts

The View DSL

A VNode represents a DOM element — the most common kind of virtual DOM node. It carries a Namespace, a tag name, a list of Attribute values and a list of child Views.

The View type

The View is a rose tree of nodes, mutually recursive with Component through view:

data View context props model action
  = VNode Namespace Tag [Attribute model action] [View context props model action] DirectEvents
  | VText (Maybe Key) MisoString
  | VComp (SomeComponent context)
  | forall props. VCompStatic (StaticPtr (SomeStaticComponent props context)) props
  | VFrag (Maybe Key) [View context props model action]

data SomeComponent context
  = forall model action props. (Eq context, Eq model, Eq props)
  => SomeComponent (Maybe Key) props (Component context props model action)

VNode and VText map one-to-one onto the physical DOM. VComp and VFrag are abstract (they live only in the virtual DOM). The existential SomeComponent is what allows embedding polymorphic components in a View. VCompStatic carries a static pointer to its constructor and is used by the native dual-thread runtime.

Element nodes

VNode HTML "div" [ HP.id_ "container" ] [ "Hello, world!" ]

In practice you rarely construct VNode directly. Use the element smart constructors from Miso.Html.Element, which fix the namespace and tag for you:

H.div_    [ HP.id_ "container" ]        [ "Hello, world!" ]
H.button_ [ HE.onClick DoSomething ]    [ "Click me" ]
H.h1_     [ HP.className "title" ]      [ text (ms pageTitle) ]

For elements not covered by Miso.Html.Element, use node (or its synonym vnode) directly:

node HTML "details" []
  [ node HTML "summary" [] [ "More info" ] ]

SVG and MathML elements use the SVG and MATHML namespaces and are covered by Miso.Svg.Element and Miso.Mathml.Element. Unlike VComp and VFrag, a VNode has a one-to-one correspondence with a physical DOM element.

node
raw constructor — namespace, tag, attributes, children
vnode
synonym for node
Miso.Html.Element
every HTML element (div_, span_, input_ …)
Miso.Svg.Element
SVG graphics, animation and container elements
Miso.Mathml.Element
MathML elements

Lifecycle hooks

Like components, elements expose lifecycle hooks:

  • onBeforeCreated
  • onCreated / onCreatedWith
  • onBeforeDestroyed / onBeforeDestroyedWith
  • onDestroyed

These are useful for initialising and tearing down third-party libraries, as in this example using highlight.js:

{-# LANGUAGE QuasiQuotes      #-}
{-# LANGUAGE MultilineStrings #-}

import Miso
import Miso.FFI.QQ (js)

data Action = Highlight DOMRef

update
  :: Action
  -> Effect context props model Action
update = \case
  Highlight domRef ->
    io_ [js| hljs.highlightElement(${domRef}) |]

view
  :: model
  -> View context props model Action
view _ =
  H.code_ [ onCreatedWith Highlight ]
    [ """
      function addOne (x) { return x + 1; }
      """
    ]

As a convention, the *With variant of a lifecycle hook (e.g. onCreatedWith) provides the target DOMRef to the callback.

The smart constructors, at a glance

node, vnode
build a VNode
text, vtext
build a VText — see Text nodes
component
build a VComp
fragment, vfrag, fragment_, vfrag_
build a VFrag
(+>)
key and mount a child Component