Skip to content

Commit 9f2464d

Browse files
author
Steven Orvell
committed
Fixes #3321. Only let dom-repeat insert elements in attached if it has been previously detached; correctly avoid re-adding children in document fragments to an element's logical linked list if they are already there.
1 parent 55b91b3 commit 9f2464d

File tree

4 files changed

+120
-4
lines changed

4 files changed

+120
-4
lines changed

src/lib/dom-tree-api.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,11 @@
195195
// the act of setting this info can affect patched nodes
196196
// getters; therefore capture childNodes before patching.
197197
for (var n=node.firstChild; n; n=n.nextSibling) {
198-
this._linkNode(n, container, ref_node);
198+
// only link in the child iff it's not already in the container's
199+
// logical tree.
200+
if (this.getParentNode(n) !== container) {
201+
this._linkNode(n, container, ref_node);
202+
}
199203
}
200204
} else {
201205
this._linkNode(node, container, ref_node);

src/lib/template/dom-repeat.html

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,15 +254,20 @@
254254
},
255255

256256
detached: function() {
257+
this.__isDetached = true;
257258
for (var i=0; i<this._instances.length; i++) {
258259
this._detachInstance(i);
259260
}
260261
},
261262

262263
attached: function() {
263-
var parent = Polymer.dom(Polymer.dom(this).parentNode);
264-
for (var i=0; i<this._instances.length; i++) {
265-
this._attachInstance(i, parent);
264+
// only perform attachment if the element was previously detached.
265+
if (this.__isDetached) {
266+
this.__isDetached = false;
267+
var parent = Polymer.dom(Polymer.dom(this).parentNode);
268+
for (var i=0; i<this._instances.length; i++) {
269+
this._attachInstance(i, parent);
270+
}
266271
}
267272
},
268273

test/smoke/distribute-dom-repeat.html

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
5+
<title>distribute dom-repeat</title>
6+
7+
<meta charset="utf-8">
8+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
9+
10+
<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
11+
<link rel="import" href="../../polymer.html">
12+
13+
</head>
14+
<body>
15+
16+
17+
<dom-module id="x-container">
18+
<template>
19+
<content select="*"></content>
20+
</template>
21+
<script>
22+
Polymer({
23+
is: 'x-container'
24+
})
25+
</script>
26+
</dom-module>
27+
28+
29+
<dom-module id="x-test">
30+
<template strip-whitespace>
31+
<x-container id="container">
32+
<template class="foo" id="nug" is="dom-repeat" items="{{model}}">
33+
<div class="foo">{{item.id}}</div>
34+
</template>
35+
</x-container>
36+
</template>
37+
<script>
38+
Polymer({
39+
is: 'x-test',
40+
41+
ready: function() {
42+
this.model = [
43+
{id: '1', text: 'How much do you like food?'},
44+
{id: '2', text: 'Where do you buy your groceries?'},
45+
{id: '3', text: 'What is your favourite colour?'}
46+
];
47+
Polymer.dom.flush();
48+
var self = this;
49+
console.log(Polymer.dom(self.$.container).firstElementChild);
50+
setTimeout(function() {
51+
console.log('***');
52+
console.log(Polymer.dom(self.$.container).firstElementChild);
53+
}, 100);
54+
}
55+
})
56+
</script>
57+
</dom-module>
58+
59+
<x-test></x-test>
60+
61+
</body>
62+
</html>

test/unit/polymer-dom-content.html

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@
4040
</script>
4141
</dom-module>
4242

43+
<dom-module id="x-dist-star">
44+
<template><content select="*"></content></template>
45+
<script>Polymer({is: 'x-dist-star'});</script>
46+
</dom-module>
47+
4348
<dom-module id="x-dist-inside-deep-tree">
4449
<template>
4550
x-dist-inside-deep-tree
@@ -243,6 +248,31 @@
243248
</script>
244249
</dom-module>
245250

251+
<dom-module id="x-repeat2">
252+
<template>
253+
<x-dist-star id="dist">
254+
<template is="dom-repeat" items="{{items}}">
255+
<div>{{item}}</div>
256+
</template>
257+
</x-dist-star>
258+
</template>
259+
<script>
260+
HTMLImports.whenReady(function() {
261+
Polymer({
262+
is: 'x-repeat2',
263+
properties: {
264+
items: {
265+
type: Array,
266+
value: ["ITEM1", "ITEM2", "ITEM3"]
267+
}
268+
}
269+
});
270+
});
271+
</script>
272+
</dom-module>
273+
274+
<x-repeat2 id="repeat2"></x-repeat2>
275+
246276
<x-compose-lazy-no-dist><span>Child</span></x-compose-lazy-no-dist>
247277

248278

@@ -1396,8 +1426,23 @@
13961426
Polymer.dom(document.body).removeChild(div);
13971427
});
13981428

1429+
test('dom-repeat that distributes inside a select=* container', function(done) {
1430+
var x1 = document.querySelector('#repeat2');
1431+
Polymer.dom.flush();
1432+
// async due to attachment.
1433+
setTimeout(function() {
1434+
assert.equal(Polymer.dom(x1.$.dist).children.length, 4);
1435+
if (x1.$.dist.shadyRoot) {
1436+
assert.equal(x1.$.dist.children.length, 4);
1437+
}
1438+
done();
1439+
});
1440+
});
1441+
13991442
});
14001443

1444+
1445+
14011446
suite('multi-content mutations', function() {
14021447

14031448
test('remove, append first content', function() {

0 commit comments

Comments
 (0)