The fastn
allows for the integration of custom web components created using
JavaScript (or other languages that compile to JavaScript).
component
, web-component
s are independent and
reusable bits of code and they have arguments.web-component
in fastn
can be created using web-component
keyword.
Here's an example of how to integrate a web component created using the standard
Web Components API.web-component.js
class HelloWorld extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
const shadow = this.shadowRoot;
const div = document.createElement('div');
div.classList.add('hello-world');
div.textContent = 'Hello World!';
div.style.color = 'orange';
div.style.borderWidth = '1px';
div.style.borderColor = 'yellow';
div.style.borderStyle = 'dashed';
div.style.padding = '10px';
shadow.appendChild(div);
}
}
customElements.define('hello-world', HelloWorld);
index.ftd
;; component call
-- hello-world:
;; Create a web component
-- web-component hello-world:
js: web-component.js
-- end: hello-world
hello-world
in
web-component.js
. Then, we've included the web component in fastn
using
the web-component
, and used it in the fastn
component tree using the
hello-world element. used it in index.ftd
.fastn
WorldsWhen working with web components, it is possible to share the data between the
JS and fastn
worlds, which can be managed and updated efficiently, reflecting
the changes in both worlds.
fastn
provides a function component_data
which exposes data arguments,
passed from fastn
world, and it's access methods. There are three access
methods provided by fastn
, against an argument:
get
: To get the value of the variable in fastn
. This method is present for
both mutable and immutable variables.set
: To set the value of the variable in fastn
. The value set using this
method will reflect it's changes in fastn
world. This method is present for
mutable variables only.on-change
: To listen for any change in variable value in fastn
world. This
method is present for both mutable and immutable variables.index.ftd
-- web-component num-to-words:
caption integer num:
js: web-component.js
web-component.js
class NumToWords extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
// `window.ftd.component_data` exposes the data
// arguments passed from `ftd` world.
let data = window.ftd.component_data(this);
// `get()` method gives the value of the argument
// passed.
let num = data.num.get();
const shadow = this.shadowRoot;
const div = document.createElement('div');
div.textContent = numberToWords(num);
div.style.color = 'orange';
div.style.borderWidth = '1px';
div.style.borderColor = 'yellow';
div.style.borderStyle = 'dashed';
div.style.padding = '10px';
shadow.appendChild(div);
}
}
customElements.define('num-to-words', NumToWords);
function numberToWords(num) {
// some code here
}
-- num-to-words: 19
fastn
and consumed by js
.js
world.index.ftd
-- integer $num: 0
-- ftd.integer: $num
-- ftd.text: I increment the `num`
$on-click$: $ftd.increment($a = $num)
-- num-to-words: $num
class NumToWords extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
let data = window.ftd.component_data(this);
let num = data.num.get();
const shadow = this.shadowRoot;
const div = document.createElement('div');
div.textContent = numberToWords(num);
div.style.color = 'orange';
div.style.borderWidth = '1px';
div.style.borderColor = 'yellow';
div.style.borderStyle = 'dashed';
div.style.padding = '10px';
// `on_change()` method listen to any changes done
// against the argument value in ftd.
data.num.on_change(function () {
const changed_value = data.num.get();
div.textContent = numberToWords(changed_value);
})
shadow.appendChild(div);
}
}
num
, whose value can be
changed by an event in fastn
. This changes is then listen using on-change
function which do the necessary changes in js
world.num
js
world too.web-component.js
class NumToWords extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
let data = window.ftd.component_data(this);
let num = data.num.get();
const shadow = this.shadowRoot;
const div = document.createElement('div');
div.textContent = numberToWords(num);
div.style.color = 'orange';
div.style.borderWidth = '1px';
div.style.borderColor = 'yellow';
div.style.borderStyle = 'dashed';
div.style.cursor = 'pointer';
div.style.padding = '10px';
div.onclick = function (_) {
let current_num = data.num.get();
current_num -= 1;
div.textContent = numberToWords(current_num);
data.num.set(current_num);
}
data.num.on_change(function () {
const changed_value = data.num.get();
div.textContent = numberToWords(changed_value);
});
shadow.appendChild(div);
}
}
index.ftd
-- num-to-words:
$num: $num
-- web-component num-to-words:
caption integer $num:
js: web-component.js
num
variable to the web-component num-to-words
which then decrements by it.num