diff --git a/src/lib/bind/accessors.html b/src/lib/bind/accessors.html
index 335634b89f..7c8b64daea 100644
--- a/src/lib/bind/accessors.html
+++ b/src/lib/bind/accessors.html
@@ -272,20 +272,33 @@
setupBindListeners: function(inst) {
var b$ = inst._bindListeners;
for (var i=0, l=b$.length, info; (i.on.-changed: = e.detail.value
- //console.log('[_setupBindListener]: [%s][%s] listening for [%s][%s-changed]', this.localName, info.path, info.id || info.index, info.property);
- //
- // TODO(sorvell): fix templatizer to support this before uncommenting
- // Optimization: only add bind listeners if the bound property is notifying...
+ // TODO: Optimization: only add bind listeners if the bound property
+ // is notifying...
var node = inst._nodes[info.index];
- //var p = node._propertyInfo && node._propertyInfo[info.property];
- //if (node._prepParentProperties || !node._propertyInfo || (p && p.notify)) {
- this._addNotifyListener(node, inst, info.event, info.changedFn);
- //}
+ // Add DOM Event listener
+ this._addNotifyListener(node, inst, info.event, info.changedFn);
+ // For path notifications add a property effect
+ if (node.addPropertyEffect) {
+ this._addNotifyEffect(node, inst, info.property, info.changedFn);
+ }
}
},
+ _addNotifyEffect: function(node, instance, property, fn) {
+ node.addPropertyEffect(property, function(path, value, old, fromAbove) {
+ if (!fromAbove && path.indexOf('.') !== -1) {
+ var ev = {
+ target: this,
+ detail: {
+ path: path,
+ value: value
+ }
+ };
+ instance._notifyListener(fn, ev);
+ }
+ });
+ },
+
// TODO(sorvell): note, adding these synchronously may impact performance,
// measure and consider if we can defer until after first paint in some cases at least.
_addNotifyListener: function(element, context, event, changedFn) {
diff --git a/src/lib/template/templatizer.html b/src/lib/template/templatizer.html
index 9aea9bd52a..25848f4b80 100644
--- a/src/lib/template/templatizer.html
+++ b/src/lib/template/templatizer.html
@@ -233,7 +233,7 @@
// Create accessors for each parent prop that forward the property to
// template instances through abstract _forwardParentProp/Path API
// that should be implemented by Templatizer users.
- var propertyEffects = this.mixin({}, this._propertyEffects);
+ var propertyEffects = {};
var propertyInfo = this.mixin({}, this._propertyInfo);
var prefixedParentProps = {};
for (prop in parentProps) {
@@ -251,6 +251,15 @@
effect: {event:
Polymer.CaseMap.camelToDashCase(parentProp) + '-changed'}
}];
+ if (template !== this) {
+ effects.push({
+ kind: 'function',
+ effect: this._createNotifyUpListener(prop),
+ fn: Polymer.Bind._functionEffect,
+ pathFn: this._functionPathEffect,
+ customNotifyUp: true
+ });
+ }
propertyEffects[parentProp] = effects;
propertyInfo[parentProp] = {};
prefixedParentProps[parentProp] = true;
@@ -283,6 +292,33 @@
}
},
+ _createNotifyUpListener: function(prop) {
+ // We simulate something like the following upwards annotation:
+ //
+ // <---|
+ // |
+ // --|
+ // ...content...
+ // The template sends a notification upwards directly to the host
+ // (skipping (this) templatizer).
+ var prefix = this._parentPropPrefix;
+ // translate: _parent_prop -> prop
+ var fn = Polymer.Bind._notedListenerFactory(prefix + prop, prop, false);
+ return function(path, value, old, fromAbove) {
+ if (!fromAbove && path.indexOf('.') !== -1) {
+ var ev = {
+ target: this,
+ detail: {
+ path: path,
+ value: value
+ }
+ };
+ // This effect is memoized, so we cannot prestore the host.
+ var host = this.parentElement.dataHost;
+ host._notifyListener(fn, ev);
+ }
+ }
+ },
_createForwardPropEffector: function(prop) {
var prefixLength = this._parentPropPrefix.length;
@@ -299,6 +335,15 @@
},
_createHostPropEffector: function(prop) {
+ // Essentially a custom notify up implementation, but has to notify
+ // sidewards b/c of the following DOM structure:
+ //
+ //
+ // --|
+ // <-|
+ // A concrete TemplateInstance sends a notification to the template
+ // (class or type).
+ // Translate: prop -> _parent_prop
var prefix = this._parentPropPrefix;
var prefixedProp = prefix + prop;
return function(path, value, old, fromAbove) {
@@ -325,9 +370,11 @@
};
},
- // Extends template with parent property info & effects and seed pre-bound data
+ // Extends template with parent property info & effects and seed pre-bound
+ // data
_extendTemplate: function(template, proto) {
- template._propertyEffects = proto._propertyEffects;
+ template._propertyEffects = this._mixPropertyEffects(
+ template._propertyEffects, proto._propertyEffects);
template._propertyInfo = proto._propertyInfo;
var prefixedParentProps = proto.prefixedParentProps;
for (var p in prefixedParentProps) {
@@ -336,6 +383,24 @@
}
},
+ _mixPropertyEffects: function(target, source) {
+ // target = target ? Polymer.Base.chainObject({}, target) : {};
+ if (!target) {
+ target = {};
+ }
+ for (var prop in source) {
+ var effects = source[prop];
+ if (prop in target) {
+ // inplace concat instead?
+ target[prop] = target[prop].concat(effects);
+ } else {
+ // slice to get shallow copy?
+ target[prop] = effects;
+ }
+ }
+ return target;
+ },
+
// Extension points for Templatizer sub-classes
/* eslint-disable no-unused-vars */
_showHideChildren: function(hidden) { },
diff --git a/src/standard/notify-path.html b/src/standard/notify-path.html
index 8c28b5e4b8..b856658c6a 100644
--- a/src/standard/notify-path.html
+++ b/src/standard/notify-path.html
@@ -96,18 +96,9 @@
if (typeof value == 'object') {
this._clearPath(path);
}
- // console.group((this.localName || this.dataHost.id + '-' + this.dataHost.dataHost.index) + '#' + (this.id || this.index) + ' ' + path, value);
// Take path effects at this level for exact path matches,
// and notify down for any bindings to a subset of this path
this._pathEffector(path, value, fromAbove, origin, originalProperty);
- // Send event to notify the path change upwards
- // Optimization: don't notify up if we know the notification
- // is coming from above already (avoid wasted event dispatch)
- if (!fromAbove) {
- // TODO(sorvell): should only notify if notify: true?
- this._notifyPathUp(path, value);
- }
- // console.groupEnd((this.localName || this.dataHost.id + '-' + this.dataHost.dataHost.index) + '#' + (this.id || this.index) + ' ' + path, value);
return true;
}
},