Easiest way for a polymer-element to declare a bindable property with a getter/setter?

polymer

Solution

A few points:

As of now you cannot publish a getter because Polymer doesn't have machinery to support it. We may improve this in the future, but it's less important as it may seem as you can do similar work with computed properties and observers. There are definitely plans afoot to have a formal computed property syntax, this should make things a bit clearer.

In general, you should not try to observe a getter, because (as Jan noted) `Object.observe` has no way of knowing if the value has changed (confusingly, it does often work under the `observe.js` polyfill because of dirty checking; even so, dirty checking a getter is a bad idea because the getter could be an arbitrarily expensive calculation [e.g. might use `offsetWidth` and force a style recalc]).

Making a bindable property read-only is not well supported. Polymer has taken an unusual approach by making data binding two-way by default. This approach was chosen as a way to reduce cognitive load on developers (data does not propagate, all bound properties simply always reflect the same value). The flip side of this is that observation side-effects are always asynchronous. In the following jsbin, I've made `count` read-only, but only in the sense that it snaps back to the private value asynchronously to any attempt to set it.

http://jsbin.com/qiboq/4/edit

Problem

Using an polymer-element's `attributes` attribute or `publish` block, it's very easy to create an attribute whose underlying storage is automatically managed. However, cases often come up where a property's value is not simply stored and retrieved. For example, a property's value may depend upon other element state. Another example: a property that's bindable but read-only. In such cases, it's nice to be able to define a property with a getter/setter pair. However, it's not clear how to declare the resulting property as bindable. If the property name is included in `attributes` or `publish`, the getter/setter won't get used. If the property name isn't declared, it doesn't appear to be bindable. And the default property behavior that results from `attributes`/`publish` only supports an onChanged handler; there's no way to reject an attempt to set a property (e.g., in a setter), nor does there seem to be a way to have a getter run when the value is retrieved. I assume that any solution here requires setting aside Polymer's declarative syntax(es) and building things from scratch. I took a shot at this: http://jsbin.com/qejaf/2/edit. That works, but I was wondering if there's an easier way to do this. E.g., is it possible to define a getter/setter (or just getter) and expose it via a `publish` block? (Aside: there's a point in that example where I'd like to be able to refer to a named element constructor, but it doesn't appear to be available during `ready`.)

Original source