DNA
Progressive Web Components.
Manipulating the DOM
Why and how
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) |
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) |
Setting innerHTML
Since DNA render cycle is responsible for Custom Element's life cycle support in old browser, directly setting the innerHTML
to an element can lead to unespected behavior. You should always consider to use the html
helper coombine with the render
method, but where it is not possible remember to invoke the customElements.upgrade
method to the root of the change:
import { customElements } from '@chialab/dna'; import './video-player.js'; const element = document.querySelector('main'); element.innerHTML = `<article> <h1>Title</h1> <video-player> <source src="/video.mp4" /> </video-player> </article>`; customElements.upgrade(element);
Integration with third party 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(); } }