Custom Elements Everywhere

Making sure frameworks and custom elements can be BFFs 🍻

What's this?

Custom Elements are the lynchpin in the Web Components specifications. They give developers the ability to define their own HTML elements. When coupled with Shadow DOM, Custom Elements should be able to work in any application. But things don't always work seamlessly.

This project runs a suite of tests against each framework to identify interoperability issues, and highlight potential fixes already implemented in other frameworks. If frameworks agree on how they will communicate with Custom Elements, it makes developers' jobs easier; they can author their elements to meet these expectations.

Custom Elements and Shadow DOM don't come with a pre-defined set of best practices. The tests in this project are a best guess as to how things should work, but they're by no means final. This project is also about driving discussion and finding consensus, so don't be afraid to open a GitHub issue to discuss places where the tests could be improved. ✌️

Angular 5.0.2

Score

30/30

100%

Handling data

Angular's default binding syntax will always set properties on an element. This works well for rich data, like objects and arrays, and also works well for primitive values so long as the Custom Element author has mapped any exposed attributes to corresponding properties.

Angular also provides binding syntax specifically for setting an attribute, if a developer would prefer to communicate with an element that way.

Handling events

Angular components can listen to native DOM events dispatched from Custom Elements. It supports all styles of events (lowercase, camelCase, kebab-case, etc).

Related Issues

Yay! No open issues!

AngularJS (1.x) 1.6.6

Score

10/30

33.33333333333333%

Handling data

AngularJS cannot bind to a custom element's attributes or properties without custom directives.

Helper libraries are available to manage these directives, such as angular-custom-elements.

Handling events

AngularJS can listen to native DOM events imperatively, by selecting the element and adding an .on() event handler. Declarative event handling is not supported.

Libraries such as angular-custom-elements can set event listeners declarative, based on particular event naming conventions.

CanJS 3.3.6

Score

26/30

86.66666666666667%

Handling data

CanJS passes all data to Custom Elements in the form of HTML attributes. For primitive data this is fine, but the system breaks down when passing rich data, like objects or arrays. In these instances, you end up with concatenated or stringified values like array-attr="1,2,3,4" or object-attr="[object Object]", which can't actually be used.

Handling events

CanJS components can listen to native DOM events dispatched from Custom Elements. It supports all styles of events (lowercase, camelCase, kebab-case, etc).

Dojo 2 2.0.0-beta3.1

Score

30/30

100%

Handling data

Dojo 2 will pass data as attributes only when the data is a type of string, otherwise it is set as a property.

Handling events

Dojo 2 can listen to native DOM events dispatched from Custom Elements. However the event names must be prefixed with on, so a Custom Event of camelEvent would be oncamelEvent. Other than that, Dojo 2 supports all kinds of event names.

Related Issues

Yay! No open issues!

hyperHTML 2.0.1

Score

30/30

100%

Handling data

hyperHTML will pass data to an element as properties, as long as the property is defined on the element's prototype. Otherwise it will fallback to passing data as attributes.

Handling events

hyperHTML can listen to native DOM events dispatched from Custom Elements. It supports all styles of events (lowercase, camelCase, kebab-case, etc).

Related Issues

Yay! No open issues!

Preact 8.2.6

Score

24/30

80%

Handling data

Preact uses a runtime heuristic to determine if it should pass data to Custom Elements as either properties or attributes. If a property is already defined on the element instance, Preact will use properties, otherwise it will fallback to attributes. The exception to this rule is when it tries to pass rich data, like objects or arrays. In those instances it will always use a property.

Handling events

Preact can listen to native DOM events dispatched from Custom Elements. However, it uses a heuristic to convert JSX event binding syntax into event names, and always lowercases the events. For example onFooUpdated={handleFoo} tells Preact to listen for an event called 'fooupdated'. This means Preact can support events with lowercase and kebab-case names, but not camelCase, PascalCase, or CAPScase events (e.g. 'URLchanged').

React 16.1.1

Score

16/30

53.333333333333336%

Handling data

React passes all data to Custom Elements in the form of HTML attributes. For primitive data this is fine, but the system breaks down when passing rich data, like objects or arrays. In these instances you end up with stringified values like some-attr="[object Object]" which can't actually be used.

Handling events

Because React implements its own synthetic event system, it cannot listen for DOM events coming from Custom Elements without the use of a workaround. Developers will need to reference their Custom Elements using a ref and manually attach event listeners with addEventListener. This makes working with Custom Elements cumbersome.

Vue 2.5.4

Score

30/30

100%

Handling data

By default, Vue passes all data to Custom Elements as attributes. However, Vue also provides syntax to instruct its bindings to use properties instead. To bind to a Custom Element property use :foo.prop="bar".

Handling events

Vue can listen to native DOM events dispatched from Custom Elements. It supports all styles of events (lowercase, camelCase, kebab-case, etc).

Related Issues

Yay! No open issues!