README
bi-st
bi-st binds elements to the window.history.state object. Its purpose is to take the long, drawn-out 99% unambiguously unidirectional markup seen here, and roll it up into a nice compact sushi roll. To help visualize this analogy, see Figure 1 below.

Figure 1
What we get is more compact and more flexible, which is good, but less clearly unidirectional, and a little less declarative, which, in my book, is not so good.
Syntax:
The syntax for binding a UI element is shown below.
<input data-st="draft.key">
<bi-st level="global"><script nomodule>
({
'[data-st]':{
onPopState: ({bist, el}) =>{
el.value = bist.pullFromPath(el.dataset.st, 'Volt ikh mit dir gefloygn vu du vilst');
},
on:{
input: ({event, bist}) => bist.merge(event.target.dataset.st, event.target.value, 'push');
}
}
})
</script></bi-st>
<p-d on="sync-history" to="{histEvent:detail.value}"></p-d>
<purr-sist write></purr-sist>
The demo shown here does the following:
- Allows the user to enter arbitary key value pairs into an object.
- The data the user enters is put into history.state.
- History.state is persisted to a remote datastore.
The total number of lines of markup is only slightly fewer than the example shown here (view source), that does the same thing without the benefit of this component. In particular, the number of lines drops from 129 lines to 110 lines.
However, as a page increases in complexity, with large numbers of UI elements, this component should help significantly reduce the amount of boilerplate. Markup shown below.
What's so great about history.state?
One of the trappings of a component library, like Vueactulitymber, is that each such library ships with a state manager / render binding. But what if you want to combine components together using different libraries? A tempting choice is to say "use Redux, or MobX, or RxJs, or CycleJS" to unify the state management. But this tends to enforce a "library / framework" choice of its own. For small applications / teams this may be fine, but what if you are working with a large application, that spans multiple generations of component libraries, involving loosely coupled teams?
Why not use the platform, and utilize something that will forevermore (?) ship with every browser? That supports time travel, and routing?
It should be noted that AMP components (like amp-bind) seem to ba based on the same principle.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Example 1</title>
</head>
<body>
<div style="display:flex;flex-direction: column">
<!-- Parse the address bar -->
<xtal-state-parse disabled="3" parse="location.href" level="global"
with-url-pattern="id=(?<storeId>[a-z0-9-]*)">
</xtal-state-parse>
<!-- If no id found in address bar, "pass-down (p-d)" message to purr-sist-myjson writer
and xtal-state-update history initializer to create a new record ("session")
in both history and remote store -->
<p-d on="no-match-found" to="purr-sist-myjson[write],xtal-state-update[init]" prop="new" val="target.noMatch" m="2" skip-init></p-d>
<!-- If id found in address bar, pass it to
the persistence reader if history is null -->
<p-d on="match-found" if="[data-history-was-null]" to="purr-sist-myjson[read]" prop="storeId" val="target.value.storeId" m="1" skip-init></p-d>
<!-- If id found in address bar, pass it to the
persistence writer whether or not history is null -->
<p-d on="match-found" to="purr-sist-myjson[write]" prop="storeId"
val="target.value.storeId" m="1" skip-init></p-d>
<!-- Read stored history.state from remote database if
id found in address bar and history starts out null -->
<purr-sist-myjson read disabled></purr-sist-myjson>
<!-- If persisted history.state found, repopulate history.state-->
<p-d on="value-changed" to="history" prop="target.value"></p-d>
<xtal-state-update init rewrite level="global"></xtal-state-update>
<!-- ========================== UI Input Fields ===================================-->
<!-- Manage binding between global history.state and UI elements -->
<bi-st disabled id="bist" level="global" url-search="(?<store>(.*?))" replace-url-value="?id=