ilyaigpetrov
ilyaigpetrov

Reputation: 3883

Polymer, observe global path, please

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.

Upvotes: 0

Views: 422

Answers (1)

ilyaigpetrov
ilyaigpetrov

Reputation: 3883

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).

Upvotes: 0

Related Questions