Skip to content

Instantly share code, notes, and snippets.

@vnys
Last active February 10, 2016 20:52
Show Gist options
  • Save vnys/5774f0d8b0eb9de06497 to your computer and use it in GitHub Desktop.
Save vnys/5774f0d8b0eb9de06497 to your computer and use it in GitHub Desktop.
es6 custom element

ES6 class syntax and custom elements with Babel

Babel's _inherits function requires the super class to be a function or null, but in Safari typeof HTMLElement is an object. Full explaination on babel/babel#1548

This solution is based on the proposed solution, but instead of rewriting HTMLElement – we just extend the function – which is safer.

Custom elements which contains other custom elements

If a custom element contains another custom element, the order of the life cycle callbacks are:

  1. Parent created
  2. Parent attached
  3. Child created
  4. Child attatched

To be able to access methods and properties on the child element from the parent element, set an attribute on the child element when it’s created, i.e. this.setAttribute('element-created', '') and use a MutationObserver in the parent element, i.e.

var childElement = document.createElement('my-child-element');
this.appendChild(childElement);

var observer = new MutationObserver( mutations => {
    mutations.forEach( mutation => {
        if (mutation.target.nodeName.toLowerCase() === 'my-child-element' && mutation.attributeName === 'element-created') {
            // do stuff
        }
    });
}).observe(childElement, { attributes: true });
var _HTMLButtonElement = function() {};
_HTMLButtonElement.prototype = HTMLButtonElement.prototype;

class MyButton extends _HTMLButtonElement {

    createdCallback() {
        this.setAttribute('element-created', '');
    }

    attachedCallback() {
        this.setAttribute('element-attached', '');
    }

    detachedCallback() { }

    attributeChangedCallback() { }

}

document.registerElement('my-button', {
    prototype: MyButton.prototype,
    extends: 'button'
});
<button is="my-button"></button>
document.createElement('button', 'my-button');
var _HTMLElement = function() {};
_HTMLElement.prototype = HTMLElement.prototype;

class MyElement extends _HTMLElement {

    createdCallback() {
        this.setAttribute('element-created', '');
    }

    attachedCallback() {
        this.setAttribute('element-attached', '');
    }

    detachedCallback() { }

    attributeChangedCallback() { }

}

document.registerElement('my-element', {
    prototype: MyElement.prototype
});


Registering the element can also be shortened:

document.registerElement('my-element', MyElement);

but it may be better to use the more verbose version for consistency (extending existing elements needs { extends: 'the-element' })

<my-element></my-element>
document.createElement('my-element');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment