0

In Polymer 1.0 you can drop {{localPropFoo.bar}} and bar will be observed for changes if you use this.set('localPropFoo.bar', 'new value'); to update its value.

But what to do if you want to bind template to an external object which is out of your control? E.g., this {{window.globalFoo.bar}} won't be bound to bar changes because external code doesn't depend on Polymer and doesn't call this.set.

Demo on codepen

Using Object.observe manually requires extra code and doesn't work in FireFox (dirty checks of observe.js to the rescue).

I want to know what is the idiomatic way of data binding to external objects out of your control.

ilyaigpetrov
  • 3,657
  • 3
  • 30
  • 46
  • Have you tried iron-signals? It can listen to any iron-signal-* event regardless of its location in the DOM. – Neil John Ramal Sep 12 '15 at 13:33
  • Idiomatic way is not to bind to external objects out of your control. Are you using other libraries that set it? If you control your whole app then there should be no need for it. – Andrey Sep 12 '15 at 15:43
  • observe-js is your only helper here, but it is clumsy approach – Andrey Sep 12 '15 at 15:43
  • @Andrey I use my own library which I don't want to depend on Polymer, but I can make it emit events in some way, maybe with Node's `EventEmitter`. – ilyaigpetrov Sep 12 '15 at 15:50
  • @ilyaigpetrov you can use native JS events – Andrey Sep 12 '15 at 19:41
  • You can alway pass change by [custom event](https://www.polymer-project.org/1.0/docs/devguide/events.html),this is how polymer achieve observe. – wener Sep 13 '15 at 15:28

1 Answers1

0

Polymer doesn't do observation out of the box, because:

  1. Object.observe support is not ubiquitous and dirty checks are expensive.
  2. Object.observe may be expensive on itself.

Supposed Solution

Catch changes yourself, call notifyPath, this.fire('global-foo-changed', {path: 'globalFoo.bar', value:...}, this.set and this.push.
They all dispatch corresponding non-bubbling (capturing) globalFoo-changed custom events (only when needed).

Why my global-foo-changed events affect only this element?

  1. global-foo-changed events are capturing (non-bubbling).
  2. Polymer elements listen for bubbling events by default.
  3. For some reason these capturing listeners capture bubble events dispatched from the same element (not from its children). Demo on codepen.

You may patch polymer with this behavior (I don't understand how it works):

SharedGlobalsBehavior = {
  properties: {
    globalFoo: {
      type: Object,
      notify: true,
      value: globalFoo
    }
  },
  created: function() {
    window.addEventListener('global-foo-changed', () => {
      if (!event.detail || !event.detail.path)
        return; // Property initialization.
      this.notifyPath(event.detail.path, event.detail.value);
    },/* if capturing */ true);
  }
};

Why No Observation Out of the Box

...sometimes imperative code needs to change an object’s sub- properties directly. As we avoid more sophisticated observation mechanisms such as Object.observe or dirty-checking in order to achieve the best startup and runtime performance cross-platform for the most common use cases, changing an object’s sub-properties directly requires cooperation from the user.

Specifically, Polymer provides two methods that allow such changes to be notified to the system: notifyPath(path, value) and set(path, value), where path is a string identifying the path (relative to the host element).

Community
  • 1
  • 1
ilyaigpetrov
  • 3,657
  • 3
  • 30
  • 46