commit 9d08230036b469ec92d53a4c593700a23016468f
parent 536345453a3e94c90795dc3b86522f4db65e142f
Author: finwo <finwo@pm.me>
Date: Thu, 29 Oct 2020 11:54:19 +0100
Automatic updating of binds & data-binding documentation
Diffstat:
3 files changed, 28 insertions(+), 26 deletions(-)
diff --git a/README.md b/README.md
@@ -61,18 +61,30 @@ registered.
Loads the template identified by the given name, surrounded by the configured
`base` and `ext`, and registers it.
+### component.render()
+
+Re-renders the component the function is called on as a template literal, using
+`component.state` as it's data input.
+
## Templates
-Loaded templates are attached to elements as shadow roots, with the addition of
-all top-layer script tags being executed having the shadow root as their `this`
-variable.
+Loaded templates are attached to elements as shadow roots after being rendered
+as template literals using your template's `.state` property as data input.
+Top-level script tags are all merged together and are used as the initialization
+code for your custom element (`this` = the element, `.root` = shadow root).
+
+Basic data-binding is supported. In your template, during initialization (so in
+the root of your scripts), you're allowed to overwrite the `this.state`
+property. Do **NOT** overwrite this property after initialization or the binding
+will cease to work. The template will be re-rendered whenever your state
+updates.
-Data binding is not included by default, but is easily added by including a
-module like [rivets](https://www.npmjs.com/package/rivets) and installing it
-like a plugin as follows:
+More advanced data-binding can be added by including a package like
+[rivets](https://www.npmjs.com/package/rivets) and installing it like a plugin
+as follows:
```js
fwebc.install(component => {
- rivets.bind(component, component);
+ rivets.bind(component.root, component.state);
});
```
diff --git a/index.js b/index.js
@@ -24,11 +24,11 @@
return true;
},
observable(obj, callback, prefix = '') {
- if (!util.isObject(obj)) {
- throw new Error(`Object is not an object, got: ${obj}`);
- }
- if ('function' !== typeof callback) {
- throw new Error(`Callback is not a function, got: ${callback}`);
+ if (Object(obj) !== obj) throw new Error(`Object is not an object, got: ${obj}`);
+ if ('function' !== typeof callback) throw new Error(`Callback is not a function, got: ${callback}`);
+ for(const key of Object.keys(obj)) {
+ if (Object(obj[key]) !== obj[key]) continue;
+ obj[key] = util.observable(obj[key], callback, `${prefix}${key}.`);
}
return new Proxy(obj, {
set(target, name, value, receiver) {
@@ -126,14 +126,6 @@
try { this.root.innerHTML = fn(...Object.values(this.state)); } catch(e) { console.error(e); }
};
- update(data) {
- Object.entries(data)
- .forEach(([key, value]) => {
- this.state[key] = util.isObject(this.state[key]) &&
- util.isObject(value) ? {...this.state[key], ...value} : value;
- });
- }
-
});
};
diff --git a/test/partial/my-app.tag b/test/partial/my-app.tag
@@ -7,14 +7,12 @@
}
</style>
<script>
- this.update({
- n: 0,
+ this.state = {
+ n : 0,
subject: 'word',
- });
+ };
setInterval(() => {
- this.update({
- n: this.state.n + 1,
- });
+ this.state.n++;
}, 1000);
</script>
</template>