fwebc.js

Toy framework for learning web components
git clone git://git.finwo.net/lib/fwebc.js
Log | Files | Refs | README

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:
MREADME.md | 26+++++++++++++++++++-------
Mindex.js | 18+++++-------------
Mtest/partial/my-app.tag | 10++++------
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>