UNPKG

@purtuga/dom-data-bind

Version:

DOM Data Bind utility. Bind data to DOM

85 lines (74 loc) 2.8 kB
import Compose from "@purtuga/common/src/jsutils/Compose.js" import { PRIVATE, arrayForEach, isString } from "./utils.js" import { getBindingFor, applyBindingsToTemplateInstance } from "./Template.js" import { render } from "./render.js"; //====================================================================== /** * Bind data to a DOM element and automatically persist changes in that data to the UI. * By default, this constructor provides interpolation of Text tokens found in the DOM * structure (represented with double curly braces: `{{ }}`). Directives can be used * by extending this constructor and adding them to the [directives]{@link DomDataBind.directives} * static property. * * @class DomDataBind * @extends Compose * * @param {String |HTMLElement} html * The HTML element that will be view and to which `data` will be bound. * * @param {Object} data * An object whose data will be used to bind to `html` element (once crated) . * */ export const DomDataBind = Compose.extend({ /** * The Element whose data was bound to. * When a string is used on input, this will be a DocumentFragment, which * means that it could be empty if its content was inserted into DOM */ $ele: null, init(html, data) { const Factory = this.getFactory(); const state = { html, data, directives: Factory.directives.slice(0) }; PRIVATE.set(this, state); if (isString(html)) { this.$ele = render(html, data, state.directives); state.bindings = this.$ele._bindings; } else { this.$ele = html; state.bindings = applyBindingsToTemplateInstance(html, getBindingFor(html, state.directives), state.directives); if (data) { this.setData(data); } } this.onDestroy(() => { arrayForEach(state.bindings, binding => binding.destroy()); delete state.data; delete state.directives; delete state.bindings; Factory.getDestroyCallback(state, PRIVATE)(); }); }, /** * Set data on to the DOM provided during initialization. * In most cases, you should never have the need to call this method. Data * provided during initialization is "live" and changes are automatically * reflected to dom. */ setData(data) { const bindings = PRIVATE.get(this).bindings; arrayForEach(bindings, binding => binding.render(data)); } }); export default DomDataBind; /** * A list of Directives to be used. * * @name DomDataBind.directives * @type {Array} */ DomDataBind.directives = [];