Procedural Web Components
Create Web Components without the class API for declarative code practices.
by Julien Etienne
HTML
<hello-element id="example"></hello-element>
<goodbye-element id="example2"></goodbye-element>
JavaScript
/**
* A procedural alternative to extending an element into a class.
*/
const createInterface = (name, type, callbacks) => {
const noop = () => {}
const customFn = {
[name]: function() {
return Reflect.construct(true ? type.prototype.constructor : type, [], customFn[name]);
}
};
const customElement = customFn[name];
customElement.prototype = Object.create(type.prototype);
if (callbacks.attributeChanged) {
customElement.prototype.attributeChangedCallback = function(attr, oldValue, newValue) {
const attributeChangedCallback = callbacks.attributeChanged || noop;
if (typeof attributeChangedCallback === 'function')
attributeChangedCallback(this, attr, oldValue, newValue);
}
} else {
callbacks.attributeChanged = customElement.prototype.attributeChangedCallback;
}
if (callbacks.connected)
customElement.prototype.connectedCallback = callbacks.connected;
if (callbacks.disconnected)
customElement.prototype.disconnectedCallback = callbacks.disconnected;
if (callbacks.adopted)
customElement.prototype.adoptedCallback = callbacks.adopted;
if (callbacks.observedAttributes)
Object.defineProperty(customElement, 'observedAttributes', {
get: function() {
return callbacks.observedAttributes();
}
});
return customElement;
}
// connectedCallback
const connected = () => console.log('connectedCallback');
// disconnectedCallback
const disconnected = () => console.log('disconnectedCallback');
// observedAttributes
const observedAttributes = () => ['name'];
// attributeChangedCallback
const attributeChanged = (element, attr, oldValue, newValue) => {
if (attr == 'name') {
element.textContent = `Hello, ${newValue}`;
}
}
// Create element using given callbacks
const HelloElement = createInterface('HelloElement', HTMLElement, {
attributeChanged,
observedAttributes,
connected,
disconnected
});
// Register custom element...