Audit Details

This is a linear deep dive of the features as I build the type checker.

element: <connection>

<connection> establishes the data: channel with a reactive tree that updates via a WebSocket.

  • not a real element
  • attribute 'name' will define the name of the connection
  • mode: attribute 'use-domain' will use the location.host to pick a document via the domain mapping parts
  • mode: attribute 'space' + attribute 'key' will find the document directly via the space and key
  • mode: attribute 'billing' will connect to the current user's billing document
  • attribute 'identity' is used for authorization
  • attribute 'redirect' will be used to redirect the page to a different location
  • attribute 'name', 'identity', 'redirect', 'space', 'key' are all reactive
  • children branch based on connection status
  • attribute 'keep-open' prevents the falling edge of connection status from from connected to disconnected from rendering the false branch

element: <connection-status>

<connection-status> is used to present the status of the connection (connected/disconnected)

  • not a real element
  • attribute 'name' is used to find the connection to reflect the status of
  • children branch of connected and disconnected (rx:else/rx:disconnected)

element: <pick>

<pick> is used to find an existing connection to use as the data channel

  • not a real element
  • attribute 'name' is used to find a previously defined connection, this connection is then re-used
  • children branch based on connection status
  • attribute 'keep-open' prevents the falling edge of connection status from from connected to disconnected from rendering the false branch

attribute: rx:expand-view-state

This attribute modifies rx:scope, rx:iterate, rx:repeat such that the scope of the view state is expanded. For example, if you scope into an object, then rx:expand-view-state will scope the view to mirror it such that the view state is isolated to that object's name.

attribute: rx:scope

This attribute is like "change directory" where you scope into a object. rx:scope="field"

  • rx:scope="field" is "cd field"
  • rx:scope="/root" is "cd /root"
  • rx:scope="../sibling is "cd ../sibling"
  • rx:scope="view:x" is like "cd /mount/tree/view/x" (or cd "V:\x)

attribute: rx:iterate

This attribute will iterate over the elements in an array or list. Unlike scope, this will change directory effectively twice because there are two levels: the list level and the element level.

  • The value follows the same rules as rx:scope EXCEPT each iterate also scopes into the element by index
  • Requires there to be exactly one child element. If this isn't the case, then a false div is injected.
  • Hint: for <table> use <tbody>

attribute rx:if, rx:ifnot

Conditions!

  • at core, rx:if and rx:ifnot are the same up beyond how the value is expressed
  • branch: "decide:$channel" will be true when there is a decision to be made based on the 'name' (default to the 'name' attribute)
  • branch: "choose:$channel"/"chosen:$channel" will be true when a value has been chosen for a multi-select as determined by channel & name
  • branch: "finalize:$channel" will be true if a multi-select is capable of being sent
  • rx:if="$path" is true when the given path evaluates to a value of true (or a value exists)
  • rx:if="$path1=$path2" is true when the given path evalutes to values that are equal
  • attribute 'force-hiding' when present will show/hide the dom element based on the true branch (this ignores rx:else from a rendering perspective)

A decision is a concept of Adama from board game days where there is an inversion of control such that the server asks the client to make a decision. This decision is determined by a channel along with a unique field determined by the name attribute. The default field is 'id'.

A multi-select decision is when the server asks "pick between #X to #Y elements from the given array."

An odd behavior of rx:if is it only renders either the true/false branches if the $path is valid and has a value.

attribute: rx:monitor

rx:monitor will watch the given path and if it is a number will trigger rx:rise and rx:fall commands

  • rx:rise is fired when the integer/number goes up (or becomes true for the first time)
  • rx:fall is fired when the integer/number goes down (or becomes false for the first time)

attribute: rx:behavior

rx:behavior is an escape hatch for very simple behaviors

See escape hatches

attribute: rx:wrap (deprecated)

rx:wrap is the precursor to rx:custom, see escape hatches

attribute: rx:custom

rx:custom behaves like rx:template except custom JavaScript code run which is registered.

see escape hatches

attribute: rx:repeat

rx:repeat is like rx:iterate except the path revolves an integer

  • as the number increases, more children are added
  • as the number decreases, the most recently added children are removed

This is useful very useful for adding form elements dynamically for a form submission

attribute: rx:switch

rx:switch works with rx:case such that path revolves a value and the DOM is constructed on the fly based on the value. The immediate children are chosen based on rx:case's value matching the value of the path resolved via rx:switch. As a side effect, this allows multiple children to be added such that complex things are built. Note: this behavior is respected in templates

<div rx:switch="thing">
    Always rendered
    <div rx:case="a">Thing is A</div>
    <div rx:case="b">Thing is B</div>
    <div rx:case="a">Thing is A</div>
</div>

attribute: rx:template

This attribute is used to control the children of the element by pulling from a <template> element

The children within a template can use rx:case to pick

element: fragment

When used within a <template>, this references the children of the invocation.

<forest>
    <template name="foo">
        <nav>
            Hello <fragment/>
        </nav>
    </template>
    <page uri="/demo">
        <div rx:template="foo">
            World
        </div>
    </page>
</forest>

fragment also has the capability of leveraging the attribute rx:case

<forest>
    <template name="foo">
        <nav>
            Hello <fragment case="name"/>!
            It is time to begin the <fragment case="task"/>
        </nav>
    </template>
    <page uri="/demo">
        <div rx:template="foo">
            <span rx:case="name">World</span>
            <span rx:case="task">Ritual</span>
        </div>
    </page>
</forest>

attribute: children-only

For rx:case usage (rx:switch and templates), the "children-only" attribute will ignore the holding element and merge the children into the parent

<forest>
    <template name="foo">
        <nav>
            Hello <fragment case="name"/>!
            It is time to begin the <fragment case="task"/>
        </nav>
    </template>
    <page uri="/demo">
        <div rx:template="foo">
            <span rx:case="name" children-only>World</span>
            <span rx:case="task" children-only>Ritual</span>
        </div>
    </page>
</forest>

element: <inline-template>

This element is like rx:template except it merges the children of the <template> element into the current parent

  • not a real element
  • children are merged into the parent

element: <todo-task>

At one point, RxHTML had a vision of having an embedded project management system for tracking TODOs...

  • should be deprecated

element: <monitor>

Like rx:monitor except introduces no dom element. Only supports rx:rise and rx:fall

  • the attribute delay controls how the signal is debounced

element: <view-write>

This is a transfer of state from anything to the view.

<view-write path="v" value="{name} is {value}" />

element: <lookup>

Simply look up a field by path and render to the DOM as a text node.

  • attribute 'path' is used to resolve to a value that is injected as a Text Node
  • attribute 'transform' is a function that makes the value more pretty. For the datetime, 'time_ago' is a nice one
  • attribute 'refresh' is used to recompute the transform based on a frequency (refresh="$x" where $x is an integer representing milliseconds)

TODO: how to add custom transforms

element: <trusted-html>

Simply look up a field by path and render to the DOM as a dom element under a 'div'

  • attribute 'path' is used to resolve to a value that is then injected via innerHTML

element: <exit-gate>

Set a guard to protect traversal away from the current page

  • attribute 'guard' is used to read only from the view a path to detect a guard

element: <title>

Normally, <title> is in the <meta> of a page, but since RxHTML operates with a forest of pages, the <title> is now part of a page based on any branch and uses a dynamic value attribute

<forest>
    <template>
        <title value="Hi {name}" />
    </template>
</forest>

element: <view-state-params>

This little neat non-element will monitor variables in the view state via "sync:$name=$path" and then dump them into the location's search after ?$name=path. This lets the view state become reactively deep linked

elements (input, textarea, select)

  • attribute rx:sync will periodically (see rx:debounce) write the value into the viewstate
  • attribute rx:debounce defines the frequency (via milliseconds) of how often the viewstate gets updated

element <sign-out>

This element will destroy the connected identity

  • attribute 'name' will define which identity to destroy