Progressive Web Components.

Backward compatibility and migration

DNA 3 comes with a compatibility layer with the 2.x version. It is called compat and it is available as module importing the @chialab/dna/compat script:

$ npm uninstall @dnajs/idom
$ npm install @chialab/dna @chialab/proteins
- import { BaseComponent, define } from '@dnajs/idom';
+ import { BaseComponent, define } from '@chialab/dna/compat';

You can also use module alias in your bundler (webpack, rollup) in order to try out the new version without code changes.

⚠️⚠️⚠️ Some features are not available in the compatibility layers and some breaking changes were needed, so we recommend to follow the migration path.

Deprecations in the compatibility layer


The template getter has been deprecated. Use the render method instead.

-get template() {
-    return () => <div>Hello</div>;
+render() {
+    return <div>Hello</div>;

The css getter has been deprecated. Use the render method instead.

-get css() {
-    return ':host { color: red; }';
+render() {
+    return <style>:host { color: red; }</style>;

The prop helper has been deprecated in favour of the property descriptor.

get properies() {
    return {
-        name: prop(String).default('Hello').observe('onNameChanged').dispatch('changename'),
+        name: {
+           type: [String],
+           defaultValue: 'Hello',
+           observers: [
+               this.onNameChanged,
+               (oldValue, newValue) => this.dispatchEvent('changename', { oldValue, newValue })
+           ]
+        },

The events getter has been deprecated in favour of the listeners getter.

- get events() {
+ get listeners() {
    return {
        click: this.onClick,

References to class methods using the name as string has been deprecated. Use direct reference to prototype methods.

get listeners() {
    return {
-        'click': 'onClick',
+        'click': this.onClick,

The observeProperty method has been deprecated in favour of the observe method.

- this.observeProperty('name', () => {});
+ this.observe('name', () => {});

The unobserveProperty method has been deprecated in favour of the unobserve method.

- this.unobserveProperty('name', () => {});
+ this.unobserve('name', () => {});

The trigger method has been deprecated in favour of the dispatchEvent method.

- this.trigger('event', details);
+ this.dispatchEvent('event', details);

The delegate method has been deprecated in favour of the delegateEventListener method.

- this.delegate('event', 'button' , listener);
+ this.delegateEventListener('event', 'button' , listener);

The undelegate method has been deprecated in favour of the undelegateEventListener method.

- this.undelegate('event', 'button' , listener);
+ this.undelegateEventListener('event', 'button' , listener);

The render helper changed the signature, now it accepts element instances instead of constructors:

- render(Article, { title: 'My first blog post' }, document.body);
+ render(new Article({ title: 'My first blog post' }), document.body);

Template function have been deprecated since they are now useless (invoking the h helper is now side-effects free).

- return () => <h1>Hello</h1>;
+ return <h1>Hello</h1>;

Zero and empty strings are no more considered falsy values. It means that while in DNA 2 the interpolation of 0 results as an empty template, DNA 3 will print '0' in text nodes and attributes.


Helpers DOM.getNodeComponent and DOM.getComponentNode and node getter have been deprecated since they are now useless. The node is the component.

-DOM.getNodeComponent(document.querySelector('.x-input')).value = 'Web Components';
+document.querySelector('.x-input').value = 'Web Components';

-DOM.getComponentNode(app).setAttribute('title', 'Web Components');
+app.setAttribute('title', 'Web Components');

-app.node.setAttribute('title', 'Web Components');
+app.setAttribute('title', 'Web Components');

Base class composability using mixins has been deprecated. Always use the Component class.


The proxy helper have been deprecated since it is now useless, see the extend method.


The trust helper has been deprecated. Use the html helper instaed.

-import { trust } from '@chialab/dna/compat';
+import { html } from '@chialab/dna/compat';


The mix has been deprecated. Import the reference directly from @chialab/proteins.

-import { mix } from '@chialab/dna/compat';
+import { mix } from '@chialab/proteins';

Custom Elements that extend builtin elements should also extend their constructors.

-import { BaseComponent } from '@chialab/dna/compat';
+import { mixin, extend, window } from '@chialab/dna/compat';

-export class XButton extends BaseComponent {
+export class XButton extends mixin(extend(window.HTMLButtonElement)) {

Custom Elements should be defined using the customElements registry.

-import { define } from '@chialab/dna/compat';
+import { customElements } from '@chialab/dna/compat';

-define('x-dialog', Dialog);
+customElements.define('x-dialog', Dialog);

Breaking changes in the compatibility layer

  • Removing a node from the document will not remove its event listeners

  • Some event validation error messages have been changed

  • Some component constructor error messages have been changed

  • Some properties validation error messages have been changed

  • Life cycle have been align with specification: now the attributeChangedCallback is called on every setAttribute even if the new value is the same of the old one, as well as connectedCallback is invoked on appendChild event if the node is already the last of the parent.


This is a list of changes requested to completely migrate to the DNA 3.0 version.

  • Install and use the new @chialab/dna instead of the @dnajs/idom module

  • Extends the Component constructor instead of the BaseComponent class

- import { BaseComponent } from '@dnajs/idom';
+ import { Component } from '@chialab/dna';

- class Card extends BaseComponent {
+ class Card extends Component {