2-way data binding in native web components
Asked Answered
H

4

17

I've been reading up on web components and am pretty intrigued by the nascent spec. Does anyone know if there is any support for 2-way data binding in the DOM, without having to use Polymer? An example would be appreciated.

Homotaxis answered 10/11, 2014 at 14:5 Comment(1)
You can give Slim.js a try. I'm not a big fan. I'm still looking for a nice soluition around the problem while avoiding any library (I'm tired to learn one DSL after another). So far my approach has been init() with template strings and update(), old fashion, similar to D3 charts.Grubstake
B
3

No, data binding isn't part of the Web Components spec.

You can of course implement data binding yourself using native JavaScript event listeners, and possibly the Proxy object, but it's probably best not to re-invent the wheel: if you want data binding, choose one of the many JavaScript frameworks out there which supports that. Polymer, React, Angular, and Vue are some recent examples of such libraries.

Brockington answered 10/11, 2014 at 15:17 Comment(1)
I don't agree with this. For a simple use case, you don't need to adopt libraries and the npm house of cards. Web components can be a simple way to go in trivial situations.Footwork
A
4

Object.observe is a potential new way to do databinding in javascript. This feature is scheduled for Ecmascript 7(javascript), but some browsers currently support it, check here. Also check out this html5rocks article on object.observe

Agglutinin answered 15/11, 2014 at 4:10 Comment(2)
Object.observe have been deprecatedOhalloran
Shame that Object.observe was deprecated...having to create a separate object (proxy), while very useful for its own reasons, is not the same thing and doesn't offer all the same benefits. Nontheless it seems there were good reasons for deprecating it: infoq.com/news/2015/11/object-observe-withdrawnUlric
B
3

No, data binding isn't part of the Web Components spec.

You can of course implement data binding yourself using native JavaScript event listeners, and possibly the Proxy object, but it's probably best not to re-invent the wheel: if you want data binding, choose one of the many JavaScript frameworks out there which supports that. Polymer, React, Angular, and Vue are some recent examples of such libraries.

Brockington answered 10/11, 2014 at 15:17 Comment(1)
I don't agree with this. For a simple use case, you don't need to adopt libraries and the npm house of cards. Web components can be a simple way to go in trivial situations.Footwork
V
3

I've been playing around with this over the last few days. You can create a StateObserver class, and extend your web components from that. A minimal implementation looks something like this:

  // create a base class to handle state
  class StateObserver extends HTMLElement {
    constructor () {
      super()
      StateObserver.instances.push(this)
    }
    stateUpdate (update) {
      StateObserver.lastState = StateObserver.state
      StateObserver.state = update
      StateObserver.instances.forEach((i) => {
        if (!i.onStateUpdate) return
        i.onStateUpdate(update, StateObserver.lastState)
      })
    }
  }

  StateObserver.instances = []
  StateObserver.state = {}
  StateObserver.lastState = {}

  // create a web component which will react to state changes
  class CustomReactive extends StateObserver {
    onStateUpdate (state, lastState) {
      if (state.someProp === lastState.someProp) return
      this.innerHTML = `input is: ${state.someProp}`
    }
  }
  customElements.define('custom-reactive', CustomReactive)

  class CustomObserved extends StateObserver {
    connectedCallback () {
      this.querySelector('input').addEventListener('input', (e) => {
        this.stateUpdate({ someProp: e.target.value })
      })
    }
  }

  customElements.define('custom-observed', CustomObserved)
<custom-observed>
  <input>
</custom-observed>
<br />
<custom-reactive></custom-reactive>

fiddle here

I like this approach because it occurs directly between precisely those elements you want to communicate with, no dom traversal to find data- properties or whatever.

Venosity answered 16/3, 2020 at 5:52 Comment(4)
How would this allow communication with other components? By making them inherit from the same StateObserver class? I’m assuming you would create a class like this for every set of components that need to communicate with each other?Genteelism
@JeremyCantrell yes, inherit from the StateObserver in order to observe state. You could create separate classes for groups of components but the usual pattern would be to have all components observing the same state. Each observing component just returns early if a change is not relevant to it as in if (state.someProp === lastState.someProp) returnVenosity
Does this mean every StateObserver element in the dom would share the same data, regardless of what object model they belong to? Seems like that would make it difficult to write a webapp with e.g. multiple views of multiple objects in multiple collections.Eventuality
This is just an answer for this specific question - it's not a new framework for building a complex webapp. That said, you could create multiple StateObserver classes if that seemed appropriate. I wouldn't though - each view could look up it's own sub set of the shared data.Venosity
H
-1

One way: $0.model = {data}; setter on $0 assigns $0.data, responding to the update, and the other way: $1.dispatchEvent(new CustomEvent('example', {detail: $1.data, cancelable: true, composed: true, bubbles: true})); with $0.addEventListenever('example', handler) gives 2 way data binding. The data object is the same, shared on 2 elements, events and setters allow responding to updates. To intercept updates to an object a Proxy works model = new Proxy(data, {set: function(data, key, value){ data[key] = value; ...respond... return true; }}) or other techniques. This addresses simple scenarios. You might also consider looking at and reading the source for Redux, it provides conventions that seem relatively popular. As Ajedi32 mentions reinventing the wheel for more complex scenarios is not so practical, unless it's an academic interest.

Hedgepeth answered 28/6, 2018 at 14:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.