To offer a simple standards compatible interface for creating a new HTML element, adding extra functionality, callbacks and properties as well as templating. Bootstraps Custom Web Component, extending from the native element; adding in extra lifecycle hooks and moving run time methods around the process stack to ensure all browsers complete actions in the correct order.
<my-component abc="xyz">Hello World</my-component>
Exports CustomHTMLElement
Extends HTMLElement (native)
Imports CustomWebComponent
Add a constructor method to your parent web component to run code when your web component is instantiated. Ensure you call super() first!
constructor() {
super();
}
Add a connected method to your parent web component to run code when your web component is added to the DOM.
connected() {
...
}
Add a disconnected method to your parent web component to run code when your web component is removed from the DOM.
disconnected() {
...
}
Add a templateUpdated method to your parent web component to run code when your web components template is re-rendered.
templateUpdated() {
...
}
Add a attributeChanged method to your parent web component to run code when your web components attributes mutate. Use this callback method to detect changes from the outside world, updating your component accordingly. Requires registration of the attributes to be monitored using observedAttributes() to return an array of names.
attributeChanged(attribute, oldValue, newValue) {
this.updateTemplate();
}
Add a attributeChanged method to your parent web component to run code when your web components attributes mutate. Use this callback method to detect changes from the outside world, updating your component accordingly. Requires registration of the attributes to be monitored using observedAttributes() to return an array of names.
propertyChanged(property, oldValue, newValue) {
this.updateTemplate();
}
Add a static template method to return a template result using lit-html's html method; convert a literal template string with embedded javascript into html that can be used to render to a users screen. Please see lit-html documents, or view the project for detailed infromation on string templating syntax.
static template() {
return html`<hello>${this.foo}</hello>`;
}
Returns an array of property names to observe for mutations. On mutation of one of these properties, propertyChanged callback is fired. Failure to register properties for observation will result in callback not being fired. Please note, when monitoring objects, changes to properties inside it will not be detected.
TIP: You can set properties on elements by prefixing with a dot <foo .bar="text"></foo>
static get observedProperties() {
return ['foo', 'bar'];
}
Returns an array of attribute names to observe for mutations. On mutation of one of these attributes, attributeChanged callback is fired. Failure to register attributes for observation will result in callback not being fired.
TIP: You set attributes on elements in the normal way <foo bar="text"></foo>
TIP: You set add/remove attributes on elements with a question mark <foo ?bar="${true}"></foo>
static get observedAttributes() {
return ['foo-one', 'bar-two'];
}
Helper function that can be run from anywhere in the web component to update the DOM with any pending changes. Any values bound to the template that have been changed, will be updated in the template. In most frameworks this is automated on mutation through observers. We do these manually as and when we need to for less overhead.
this.updateTemplate();
import { CustomHTMLElement, html } from "../../node_modules/custom-web-component/index.js";
/**
* HelloWorld
* A sample Custom HTML Element, to be used in any system that is capable of outputting HTML
* Build on Web Standards and polyfilled for legacy browsers, using a simple clean lite HTML template rendering called lit-html
*/
class HelloWorld extends CustomHTMLElement {
/**
* @public constructor()
* Invoked when instantiation of class happens
* NOTE: Call super() first!
* NOTE: Declare local properties here... [this.__private, this._protected, this.public]
* NOTE: Declarations and kick starts only... no business logic here!
*/
constructor() {
super();
this.foo = 'FOO!!';
this.bar;
}
/**
* template()
* Return html TemplateResolver a list of observed properties, that will call propertyChanged() when mutated
* @return {TemplateResult} Returns a HTML TemplateResult to be used for the basis of the elements DOM structure
*/
static template() {
return html`
<style>
/* Style auto encapsulates in shadowDOM or shims for IE */
:host { ... }
div { ... }
</style>
<div>
<button @click="${this._clicked.bind(this, 'hello')}">${this.foo}</button>
</div>
`;
}
/**
* @static @get observedProperties()
* Return a list of observed properties, that will call propertyChanged() when mutated
* @return {Array} List of properties that will promote the callback to be called on mutation
*/
static get observedProperties() { return [...] }
/**
* @public propertyChanged()
* Invoked when an observed instantiated property has changed
* @param {String} property The name of the property that changed
* @param {Mixed} oldValue The old value before hte change
* @param {Mixed} newValue The new value after the change
*/
propertyChanged(property, oldValue, newValue) {
this.updateTemplate();
}
/**
* @static @get observedAttributes()
* Return a list of observed attributes, that will call attributeChanged() when mutated
* @return {Array} List of attributes that will promote the callback to be called on mutation
*/
static get observedAttributes() { return [...] }
/**
* @public attributeChanged()
* Invoked when an observed node attribute has changed
* @param {String} attribute The name of the attribute that changed
* @param {Mixed} oldValue The old value before hte change
* @param {Mixed} newValue The new value after the change
*/
attributeChanged(attribute, oldValue, newValue) {
this.updateTemplate();
}
/**
* @public connected()
* Invoked when node is connected/added to the DOM
*/
connected() { ... }
/**
* @public disconnected()
* Invoked when node is disconnected/removed from the DOM
*/
disconnected() { ... }
/**
* @public update()
* Update the view, pushing only changes for update in shadow DOM
*/
templateUpdated() { ... }
/**
* @private _clicked()
* You clicked the button
* @param {String} hello The text passed in by method
* @param {Event} ev The Event that kicked the method
*/
_buttonClicked(hello, ev) {
this.foo = hello;
this.updateTemplate();
}
}
customElements.define('hello-world', HelloWorld);