Skip to content

User Interface Spec

aaronc edited this page Nov 13, 2014 · 1 revision

freactive-based User Interface Spec

User interface libraries based on freactive understand some variant of Hiccup-style syntax. This was chosen because it provides a fairly simple representation of a "virtual node" that works with any number of node types (as opposed to a factory-function based models that require a function for each known node).

Specification

A "virtual node" is represented by a vector whose first element is a keyword, as in Hiccup, is a keyword representing the node type with optional CSS-like shortcuts for id and class attributes where they are available. Examples: :text, :text#my-text.a-style. Node type keywords can be namespace prefixed if that makes sense for the underlying UI framework.

If the second element of the vector is a map, it should be treated as a map of attributes with keyword keys. Any attribute keys beginning with :on- should be treated as events which take a Clojure function as an event handler and optionally core.async channels into which the events will be put!. Other attributes values can either be literal values or instances of IDeref (such as a reactive atom, rx, etc.). If an instance of IDeref is passed in as an attribute value, the underlying UI framework will attempt to attach an invalidation watch or watch to the underlying ref and update the node's attribute when the ref changes.

Example:

(ns test1
 (:refer-clojure :exclude [atom])
 (:require [freactive.core :refer [atom rx]]))

(defn create-elem []
 (let [clicked (atom 0)]
  [:button {:on-click (fn [e] (swap! clicked inc)) :text (rx (str @clicked))}])

(my-ui-framework/show (create-elem))

The remaining elements of the vector will be treated as children of the node. Child elements can be one of

  • literal values (such as text strings) appropriate for the given node
  • nodes themselves
  • vectors representing nodes (beginning with a keyword)
  • sequences of other nodes (for easy composition)
  • instances of IDeref which should be handled as reactive nodes by the underlying framework
Clone this wiki locally