diff --git a/src/lib/template/dom-repeat.html b/src/lib/template/dom-repeat.html
index 63c548a328..72067e0988 100644
--- a/src/lib/template/dom-repeat.html
+++ b/src/lib/template/dom-repeat.html
@@ -342,9 +342,10 @@
this._debounceTemplate(this._render);
},
- _observeChanged: function() {
- this._observePaths = this.observe &&
- this.observe.replace('.*', '.').split(' ');
+ _observeChanged: function(observe) {
+ // All observed paths are handled as wildcard/deep observation. So if
+ // the user specifies a wildcard, we just strip it.
+ this._observePaths = observe && observe.replace('.*', '').split(' ');
},
_itemsChanged: function(change) {
@@ -366,29 +367,57 @@
this._keySplices = this._keySplices.concat(change.value.keySplices);
this._indexSplices = this._indexSplices.concat(change.value.indexSplices);
this._debounceTemplate(this._render);
+ } else if (change.path === 'items.length') {
+ // nothing to do
} else { // items.*
// slice off 'items.' ('items.'.length == 6)
var subpath = change.path.slice(6);
- this._forwardItemPath(subpath, change.value);
- this._checkObservedPaths(subpath);
+ var headTail = this._splitHeadTail(subpath);
+ var key = headTail.head;
+ var path = headTail.tail;
+ this._forwardItemPath(key, path, change.value);
+ if (this._shouldResortOrFilter(key, path)) {
+ // TODO(kschaaf): interim solution: ideally this is just an
+ // incremental insertion sort of the changed item
+ this._needFullRefresh = true;
+ if (this.delay) {
+ this.debounce('render', this._render, this.delay);
+ } else {
+ this._debounceTemplate(this._render);
+ }
+ }
}
},
- _checkObservedPaths: function(path) {
- if (this._observePaths) {
- path = path.substring(path.indexOf('.') + 1);
+ _splitHeadTail: function(path) {
+ var dot = path.indexOf('.');
+ if (dot === -1) {
+ return {head: path};
+ } else {
+ var head = path.slice(0, dot);
+ var tail = path.slice(dot + 1);
+ return {head: head, tail: tail};
+ }
+ },
+
+ _shouldResortOrFilter: function(key, path) {
+ if (!this._sortFn && !this._filterFn) {
+ return;
+ }
+ if (this._needFullRefresh) {
+ return;
+ }
+
+ if (path === undefined) {
+ return true;
+ } else if (this._observePaths) {
var paths = this._observePaths;
for (var i=0; i. path change,
// responsible for notifying item. changes to inst for key
- _forwardItemPath: function(path, value) {
+ _forwardItemPath: function(key, path, value) {
if (this._keyToInstIdx) {
- var dot = path.indexOf('.');
- var key = path.substring(0, dot < 0 ? path.length : dot);
var idx = this._keyToInstIdx[key];
var inst = this._instances[idx];
if (inst && !inst.isPlaceholder) {
- if (dot >= 0) {
- path = this.as + '.' + path.substring(dot+1);
+ if (path !== undefined) {
+ path = this.as + '.' + path;
inst._notifyPath(path, value, true);
} else {
inst.__setProperty(this.as, value, true);
diff --git a/test/unit/dom-repeat.html b/test/unit/dom-repeat.html
index be42bb7d19..e5fd7e8e32 100644
--- a/test/unit/dom-repeat.html
+++ b/test/unit/dom-repeat.html
@@ -3252,6 +3252,52 @@ x-repeat-chunked
});
});
+ suite('re-trigger sort or filter', function() {
+
+ var repeater;
+
+ setup(function() {
+ var el = document.createElement('x-primitive-large');
+ repeater = el.$.repeater;
+ repeater.sort = function() {};
+ repeater.filter = function() {};
+ repeater.render();
+ });
+
+ test('no observe set', function() {
+ assert.isTrue(repeater._shouldResortOrFilter('#2'));
+ assert.notOk(repeater._shouldResortOrFilter('#1', 'subproperty'));
+ });
+
+ test('observe property', function() {
+ repeater.observe = 'foo.bar';
+
+ assert.isTrue(repeater._shouldResortOrFilter('#2'));
+ assert.isTrue(repeater._shouldResortOrFilter('#2', 'foo'));
+ assert.isTrue(repeater._shouldResortOrFilter('#2', 'foo.bar'));
+ assert.isTrue(repeater._shouldResortOrFilter('#2', 'foo.bar.baz'));
+
+ assert.notOk(repeater._shouldResortOrFilter('#2', 'foobar'));
+ assert.notOk(repeater._shouldResortOrFilter('#2', 'foo.bars'));
+ assert.notOk(repeater._shouldResortOrFilter('#2', 'foo.baz'));
+ assert.notOk(repeater._shouldResortOrFilter('#1', 'subproperty'));
+ });
+
+ test('observe deep property', function() {
+ repeater.observe = 'foo.bar.*';
+
+ assert.isTrue(repeater._shouldResortOrFilter('#2'));
+ assert.isTrue(repeater._shouldResortOrFilter('#2', 'foo'));
+ assert.isTrue(repeater._shouldResortOrFilter('#2', 'foo.bar'));
+ assert.isTrue(repeater._shouldResortOrFilter('#2', 'foo.bar.baz'));
+
+ assert.notOk(repeater._shouldResortOrFilter('#2', 'foobar'));
+ assert.notOk(repeater._shouldResortOrFilter('#2', 'foo.bars'));
+ assert.notOk(repeater._shouldResortOrFilter('#2', 'foo.baz'));
+ assert.notOk(repeater._shouldResortOrFilter('#1', 'subproperty'));
+ });
+ });
+
suite('repeater API', function() {
test('modelForElement', function() {