Web Component

The ftd allows for the integration of custom web components created using JavaScript (or other languages that compile to JavaScript).

Like component, web-components are independent and reusable bits of code and they have arguments.

Create Your Web Component

A “web-component” in ftd 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);
index.ftd
;; component call
-- hello-world:

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

-- end: word-count
In above code we have create a web component hello-world in web-component.js. Then, we’ve included the web component in the ftd using the web-component , and used it in the ftd component tree using the hello-world element. used it in index.ftd.
Output

Data Across JS and ftd Worlds

When working with web components, it is possible to share the data between the JS and ftd worlds, which can be managed and updated efficiently, reflecting the changes in both worlds.

ftd provides a function component_data which exposes data arguments, passed from ftd world, and it’s access methods. There are three access methods provided by ftd, against an argument:

  • get: To get the value of the variable in ftd. This method is present for both mutable and immutable variables.
  • set: To set the value of the variable in ftd. The value set using this method will reflect it’s changes in ftd world. This method is present for mutable variables only.
  • on-change: To listen for any change in variable value in ftd 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
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
}
Now lets call this component and pass a data.
Input
-- num-to-words: 19
Output
Output
We have seen how data can be passed from ftd 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
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);
    }
}
In above example, we have added a mutable variable num, whose value can be changed by an event in ftd. 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);
    }
}
index.ftd
-- num-to-words:
$num: $num

-- web-component num-to-words:
caption integer $num:
js: web-component.js
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 to show your support!

Getting Help

Have a question or need help?

Visit our GitHub Q&A discussion to get answers and subscribe to it to stay tuned.

Join our Discord channel and share your thoughts, suggestion, question etc.

Connect with our community!

Found an issue?

If you find some issue, please visit our GitHub issues to tell us about it.

Join us

We welcome you to join our Discord 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 - FifthTry.com