Skip to content

Commit

Permalink
Improvements to binding API:
Browse files Browse the repository at this point in the history
- Adds override points for _parseBindings and _evaluateBinding
- Adds support for runtime template binding
- Moves ready(), _hasAccessor tracking, and instance property swizzle at ready time to PropertyAccessors
  • Loading branch information
kevinpschaaf committed Apr 7, 2017
1 parent dd4e323 commit ea4e7d9
Show file tree
Hide file tree
Showing 7 changed files with 540 additions and 462 deletions.
3 changes: 1 addition & 2 deletions lib/elements/dom-bind.html
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@
observer.observe(this, {childList: true});
return;
}
this._bindTemplate(template);
this.root = this._stampTemplate(template);
this.root = this._stampBoundTemplate(template);
this.__children = [];
for (let n=this.root.firstChild; n; n=n.nextSibling) {
this.__children[this.__children.length] = n;
Expand Down
9 changes: 7 additions & 2 deletions lib/mixins/element-mixin.html
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@
if (window.ShadyCSS) {
window.ShadyCSS.prepareTemplate(template, is, ext);
}
proto._bindTemplate(template, propertiesForClass(proto.constructor));
proto._bindTemplate(template);
}

function flushPropertiesStub() {}
Expand Down Expand Up @@ -620,7 +620,7 @@
ready() {
if (this._template) {
hostStack.beginHosting(this);
this.root = this._stampTemplate(this._template);
this.root = this._stampBoundTemplate(this._template);
hostStack.endHosting(this);
}
super.ready();
Expand Down Expand Up @@ -745,6 +745,11 @@
return Polymer.ResolveUrl.resolveUrl(url, base);
}

static _parseTemplateContent(template, templateInfo, nodeInfo) {
templateInfo.dynamicFns = templateInfo.dynamicFns || propertiesForClass(this);
return super._parseTemplateContent(template, templateInfo, nodeInfo);
}

}

return PolymerElement;
Expand Down
86 changes: 71 additions & 15 deletions lib/mixins/property-accessors.html
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@
_initializeProperties() {
this.__serializing = false;
this.__dataCounter = 0;
this.__dataInitialized = false;
this.__dataInvalid = false;
// initialize data with prototype values saved when creating accessors
this.__data = {};
Expand All @@ -137,6 +138,16 @@
if (this.__dataProto) {
this._initializeProtoProperties(this.__dataProto);
}
// Capture instance properties; these will be set into accessors
// during first flush. Don't set them here, since we want
// these to overwrite defaults/constructor assignments
for (let p in this.__dataHasAccessor) {
if (this.hasOwnProperty(p)) {
this.__dataInstanceProps = this.__dataInstanceProps || {};
this.__dataInstanceProps[p] = this[p];
delete this[p];
}
}
}

/**
Expand Down Expand Up @@ -347,15 +358,31 @@
* @protected
*/
_createPropertyAccessor(property, readOnly) {
saveAccessorValue(this, property);
Object.defineProperty(this, property, {
get: function() {
return this.__data[property];
},
set: readOnly ? function() { } : function(value) {
this._setProperty(property, value);
}
});
if (!this.hasOwnProperty('__dataHasAccessor')) {
this.__dataHasAccessor = Object.assign({}, this.__dataHasAccessor);
}
if (!this.__dataHasAccessor[property]) {
this.__dataHasAccessor[property] = true;
saveAccessorValue(this, property);
Object.defineProperty(this, property, {
get: function() {
return this.__data[property];
},
set: readOnly ? function() { } : function(value) {
this._setProperty(property, value);
}
});
}
}

/**
* Returns true if this library created an accessor for the given property.
*
* @param {string} property Property name
* @return {boolean} True if an accessor was created
*/
_hasAccessor(property) {
return this.__dataHasAccessor && this.__dataHasAccessor[property];
}

/**
Expand Down Expand Up @@ -436,12 +463,41 @@
* @protected
*/
_flushProperties() {
let oldProps = this.__dataOld;
let changedProps = this.__dataPending;
this.__dataPending = null;
this.__dataCounter++;
this._propertiesChanged(this.__data, changedProps, oldProps);
this.__dataCounter--;
if (!this.__dataInitialized) {
this.ready()
} else if (this.__dataPending) {
let oldProps = this.__dataOld;
let changedProps = this.__dataPending;
this.__dataPending = null;
this.__dataCounter++;
this._propertiesChanged(this.__data, changedProps, oldProps);
this.__dataCounter--;
}
}

/**
* Lifecycle callback called the first time properties are being flushed.
* Prior to `ready`, all property sets through accessors are queued and
* their effects are flushed after this method returns.
*
* Users may override this function to implement behavior that is
* dependent on the element having its properties initialized, e.g.
* from defaults (initialized from `constructor`, `_initializeProperties`),
* `attributeChangedCallback`, or values propagated from host e.g. via
* bindings. `super.ready()` must be called to ensure the data system
* becomes enabled.
*
* @public
*/
ready() {
// Update instance properties that shadowed proto accessors; these take
// priority over any defaults set in constructor or attributeChangedCallback
if (this.__dataInstanceProps) {
Object.assign(this, this.__dataInstanceProps);
}
this.__dataInitialized = true;
// Run normal flush
this._flushProperties();
}

/**
Expand Down
Loading

0 comments on commit ea4e7d9

Please sign in to comment.