CustomElement
In this section, you will explore the fundamental structure of Monster.js web components. These components adhere to the Web Components standard, a set of modern browser technologies that allow for the creation of reusable, encapsulated HTML elements. By leveraging this standard, Monster.js components ensure compatibility with web platforms and enable developers to build robust, modular, and maintainable web applications. Understanding this foundational structure is key to effectively utilizing Monster.js to create custom elements with powerful capabilities.
CustomElement Class
The CustomElement class serves as the foundation for all our components. It unifies certain behaviors and also provides templating functionalities.
Understanding the Structure
To understand the basic structure, it is essential to first review the Web Components standard, especially the call flow.
Shadow DOM in Monster.js Components
Our components heavily utilize the shadowRoot concept, which encapsulates the internal workings of the component and hides them from the outside. This approach offers numerous advantages, such as style encapsulation.
Creating a Custom Component
Let’s go through an example to see how you can work with the base class to create a custom component.
Creating a Custom Class
First, we create a class that extends CustomElement. The parent class already implements several functions that simplify the process:
class MyButton extends CustomElement {
}
The Monster Button is typically derived from the customcontrol class, which provides additional features optimized for form handling. However, in this section, we will focus only on the basic CustomControl functionalities relevant to button controls.
Defining a Custom HTML Tag
The next step is to define which HTML tag the control will use:
class MyButton extends CustomElement {
static getTag() {
return "monster-my-button";
}
}
Configuring Options
To allow for customization, we need to create a structure for setting options. We can leverage the existing structure in CustomElement and extend it by adding the default property:
class MyButton extends CustomElement {
get defaults() {
return Object.assign({}, super.defaults, {});
}
}
Creating a Template
We define the component's template through the templates.main option. For example, we can create a simple button using HTML5:
<button>Hello!</button>
The template can be incorporated into the default structure as follows:
return Object.assign({}, super.defaults, {
templates: {
main: "<button>Hello!</button>"
},
});
For more complex templates, you can move the HTML into a separate function and call it:
return Object.assign({}, super.defaults, {
templates: {
main: getTemplate()
},
});
Template Mapping
You can also map key values to the HTML template using templateMapping:
return Object.assign({}, super.defaults, {
templateMapping: {
a: "b"
},
});
The template then contains these placeholders. This is useful if you want to set certain values dynamically from outside.
<button>${a}</button>
In this case, the placeholder ${a} will be replaced with the value of a when the component is rendered. In this example, the value of a is b, therefore, the button will display b.
If you want to use another marker than ${}, you can set it in the templateMapping as well:
return Object.assign({}, super.defaults, {
templateFormatter: {
marker: {
open: "<%",
close: "%>"
}
}
Using the Component
By adding the <monster-my-button> tag to your HTML, you will see a simple button:
<monster-my-button></monster-my-button>
Before you see the button, you need to register the component:
registerCustomElement(MyButton);A rookie might say, "It's just a button, why all the fuss?" But as a skilled developer, you see the potential it holds. Now, you have a fully configurable, well-encapsulated, and beautifully designed button!
Isn't that cool?
Handling Lifecycle Callbacks
Web components have lifecycle methods, such as connectedCallback and disconnectedCallback, which are called when the control is added or removed from the DOM, respectively.
class MyButton extends CustomElement {
connectedCallback() {
super.connectedCallback();
}
disconnectedCallback() {
super.disconnectedCallback();
}
}
In this function, you can perform additional tasks, such as setting up event listeners or cleaning up resources.
It is important to call the parent method, as it performs essential tasks, such as setting up the shadow DOM.
Initializing and Assembling Methods
In addition to lifecycle methods, the CustomElement class provides two key methods: initMethodSymbol and assembleMethodSymbol. These can be overridden for initialization and assembly:
import {
assembleMethodSymbol,
initMethodSymbol,
} from "@schukai/monster/dist/modules/dom/customelement.js";
class MyButton extends CustomElement {
[initMethodSymbol]() {
super[initMethodSymbol]();
}
[assembleMethodSymbol]() {
super[assembleMethodSymbol]();
}
}
The initMethodSymbol method is called from the constructor and is used for one-time initialization. The assembleMethodSymbol is invoked when the control is first added to the DOM.