DNA
Progressive Web Components.
Integrations
Frameworks
DNA uses its own render to handle slotted nodes in the light DOM. So, we run tests for integration with other frontend frameworks like React, Angular, Lit and Vue. Here is a list of passing tests and known issues:
Framwework | Update a property | Slot text | Slot elements | Named |
---|---|---|---|---|
React | ⚠️1 | ✅ | ✅ | ✅ |
Lit | ✅2 | ✅ | ✅ | ⚠️3 |
Vue | ✅2 | ⚠️5 | ⚠️5 | ⚠️5 |
Angular | 🚧 | 🚧 | 🚧 | 🚧 |
1 partial support in React is granted primitive properties, but not for reference values before React 19.
2 support in Lit is granted using property expressions.
3 partial support in Lit is granted for first render, but inserting/removing children may lead to render issues.
4 support in Vue is granted using property expressions.
5 partial support in Vue is granted for first render and insterted children, but removing children may lead to render issues.
View libraries
Sometimes you need to encapsulate in DNA another UI library, like Mapbox or Pickr. Since DNA components are DOM nodes, the integration is possible using the element context as library param:
import { Component, customElement } from '@chialab/dna'; import Pickr from '@simonwep/pickr'; @customElement('color-picker') export class ColorPicker extends Component { private pickr: Pickr; connectedCallback() { super.connectedCallback(); this.pickr = new Pickr({ el: this, }); } disconnectedCallback() { this.pickr.destroyAndRemove(); super.disconnectedCallback(); } }
Manipulating the DOM
Since DNA does not require any Custom Elements polyfill, the life cycle is delegated to the render cycle which uses the DOM
helper under the hood. This helper invokes the life cycle methods for each DOM operation like appendChild
, removeChild
etc.
If you want to manipulate the DOM tree outside of a render cycle, always use DOM
methods instead of the HTMLElement
prototype:
import { ChildComponent } from './child-component'; const child = new ChildComponent(); // ✘ DON'T document.body.appendChild(child); // ✔︎ DO! DOM.appendChild(document.body, child);
All methods inherit the prototype signature with the context node as first argument:
HTMLElement.prototype |
DOM helper |
---|---|
appendChild(newChild) |
appendChild(parent, newChild) |
removeChild(oldChild) |
removeChild(parent, oldChild) |
insertBefore(newChild, refChild) |
insertBefore(parent, newChild, refChild) |
replaceChild(newChild, oldChild) |
replaceChild(parent, newChild, oldChild) |
insertAdjacentElement(position, instertedElement) |
insertAdjacentElement(parent, position, instertedElement) |
getAttribute(qualifiedName) |
getAttribute(element, qualifiedName) |
hasAttribute(qualifiedName) |
hasAttribute(element, qualifiedName) |
setAttribute(qualifiedName, value) |
setAttribute(element, qualifiedName, value) |
removeAttribute(qualifiedName) |
removeAttribute(element, qualifiedName) |
dispatchEvent(event) |
dispatchEvent(element, event) |
matches(selector) |
matches(element, selector) |