Skip to content

Commit 46bf571

Browse files
author
Dierk Koenig
committed
examples: add specialized example for synchronizing input values by asynchronously connecting to a remote observable map.
1 parent a87c8c2 commit 46bf571

File tree

1 file changed

+79
-0
lines changed

1 file changed

+79
-0
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Async Controllers with Observable Map Example</title>
6+
<link rel="shortcut icon" type="image/png" href="../../../img/logo/logo-60x54.png"/>
7+
<link rel="stylesheet" href="../../../css/kolibri-base.css">
8+
<style>
9+
body {
10+
max-width: 42em;
11+
margin: 3em auto 3em auto;
12+
}
13+
main {
14+
display: grid;
15+
grid-template-columns: repeat(3, max-content);
16+
gap: .5em 2em;
17+
}
18+
input {
19+
field-sizing: content; /* atm only works in chrome (June 2025)*/
20+
}
21+
</style>
22+
</head>
23+
<body>
24+
<h1>Async Observable Map Example</h1>
25+
<p> Sharing values in classical MVC with the help of observable maps.</p>
26+
<p> The maps synchronize asynchronously via a remote observable map.</p>
27+
<p> Change any input to see the others update immediately.</p>
28+
<p> Hit multiple buttons to see how updates intermix without loss of consistency.</p>
29+
<main id="main">
30+
</main>
31+
32+
<script type="module">
33+
34+
import {ObservableMap} from "../../kolibri/observable/observableMap.js";
35+
import {SimpleInputController} from "../../kolibri/projector/simpleForm/simpleInputController.js";
36+
import {InputProjector} from "../../kolibri/projector/simpleForm/simpleInputProjector.js";
37+
import {times} from "../../kolibri/util/arrayFunctions.js";
38+
import {AsyncRelay} from "../../kolibri/observable/asyncRelay.js";
39+
import {dom} from "../../kolibri/util/dom.js";
40+
41+
const remoteObservableMap = ObservableMap("remote");
42+
const sharedKey = "sharedKey";
43+
44+
times(8)( n => {
45+
const observableMap = ObservableMap("map-"+n);
46+
// make a controller
47+
const ctrl = SimpleInputController({
48+
label: "First Name " + n,
49+
name: "firstname",
50+
type: "text",
51+
value: "Dierk",
52+
});
53+
54+
const [button] = dom(`<button>multiple async changes</button>`);
55+
button.addEventListener("click", _e => {
56+
times(5)(j=> {
57+
setTimeout(
58+
_=>{ ctrl.setValue(ctrl.getValue() + String(j))}
59+
, 500*(j++));
60+
});
61+
});
62+
main.append(button);
63+
64+
// project the controlled data
65+
main.append(...InputProjector.projectInstantInput(ctrl, "noCssClass"));
66+
67+
// bidirectional binding to observable map
68+
observableMap.onChange( (key, value) => sharedKey === key ? ctrl.setValue(value.toString()) : null );
69+
ctrl.onValueChanged( val => observableMap.setValue(sharedKey, val));
70+
71+
AsyncRelay(remoteObservableMap)(observableMap);
72+
});
73+
74+
75+
</script>
76+
77+
78+
</body>
79+
</html>

0 commit comments

Comments
 (0)