Support us by giving us a
star on Github 🚀

Web Component

The `fastn` allows for the integration of custom web components created using JavaScript (or other languages that compile to JavaScript). Like [`component`](/ftd/component/), `web-component`s are independent and reusable bits of code and they have arguments.

Create Your Web Component

A `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();
const shadow = this.attachShadow({ mode: 'open' });
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);
Lang:
js
`index.ftd`
;; component call
-- hello-world:

;; Create a web component
-- web-component hello-world:
js: web-component.js

-- end: word-count
Lang:
ftd
In above code we have created a web component `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`.
Output

Data Across JS and `fastn` Worlds

When 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. Let's look at these in more detail.

A Web Component With Argument

Lets create a web component that takes an argument.
`index.ftd`
-- web-component num-to-words:
caption integer num:
js: web-component.js
Lang:
ftd
`web-component.js`
class NumToWords extends HTMLElement {
constructor() {
super();
// `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.attachShadow({ mode: 'open' });
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
}
Lang:
js
Now lets call this component and pass a data.
Input
-- num-to-words: 19
Lang:
ftd
Output
Output
We have seen how data can be passed from `fastn` and consumed by `js`.

Working with mutable data

Now let's mutate the data and correspondingly change the output from `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
Lang:
ftd
class NumToWords extends HTMLElement {
constructor() {
super();
let data = window.ftd.component_data(this);
let num = data.num.get();

const shadow = this.attachShadow({ mode: 'open' });
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);
}
}
Lang:
ftd
In above example, we have added a mutable variable `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.
Output
0
I increment the `num`
Now let mutate the data from `js` world too.
`web-component.js`
class NumToWords extends HTMLElement {
constructor() {
super();
let data = window.ftd.component_data(this);
let num = data.num.get();

const shadow = this.attachShadow({ mode: 'open' });
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);
}
}
Lang:
ftd
`index.ftd`
-- num-to-words:
$num: $num

-- web-component num-to-words:
caption integer $num:
js: web-component.js
Lang:
ftd
In the above code as you can see that we are passing the mutable reference of `num` variable to the web-component `num-to-words` which then decrements by it.
Output
0
I increment the `num`

Support `fastn`!

Enjoying `fastn`? Please consider giving us a star ⭐️ on [GitHub](https://github.com/fastn-stack/fastn) to show your support!
[⭐️](https://github.com/fastn-stack/fastn)

Getting Help

Have a question or need help? Visit our [GitHub Q&A discussion](https://github.com/fastn-stack/fastn/discussions/categories/q-a) to get answers and subscribe to it to stay tuned. Join our [Discord](https://discord.gg/a7eBUeutWD) channel and share your thoughts, suggestion, question etc. Connect with our [community](/community/)!
[💻️](/community/)

Found an issue?

If you find some issue, please visit our [GitHub issues](https://github.com/fastn-stack/fastn/issues) to tell us about it.

Quick links:

- [Install `fastn`](install/) - [Create `fastn` package](create-fastn-package/) - [Expander Crash Course](expander/) - [Syntax Highlighting in Sublime Text](/sublime/)

Join us

We welcome you to join our [Discord](https://discord.gg/a7eBUeutWD) community today. We are trying to create the language for human beings and we do not believe it would be possible without your support. We would love to hear from you.
Copyright © 2023 - fastn.com