From 2aba4335b0060eced1931c5a052dca3107afb8fa Mon Sep 17 00:00:00 2001 From: Jacob Wright Date: Tue, 11 Sep 2018 20:13:00 -0600 Subject: [PATCH] Fixes keyed each blocks where items move within the array but do not move in the DOM Fixes #1624 ensuring that * blocks that use "current" include outros that set it to false * when a block is moved inside a keyed each block, call outro before intro again --- src/compile/dom/Block.ts | 4 ++ src/shared/keyed-each.js | 9 ++-- .../expected-bundle.js | 7 ++-- .../each-block-keyed/expected-bundle.js | 7 ++-- .../each-block-keyed-component/Todo.html | 1 + .../each-block-keyed-component/_config.js | 41 +++++++++++++++++++ .../each-block-keyed-component/main.html | 10 +++++ .../Widget.html | 1 + .../_config.js | 23 +++++++++++ .../main.html | 9 ++++ 10 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 test/runtime/samples/each-block-keyed-component/Todo.html create mode 100644 test/runtime/samples/each-block-keyed-component/_config.js create mode 100644 test/runtime/samples/each-block-keyed-component/main.html create mode 100644 test/runtime/samples/transition-js-nested-each-keyed-move/Widget.html create mode 100644 test/runtime/samples/transition-js-nested-each-keyed-move/_config.js create mode 100644 test/runtime/samples/transition-js-nested-each-keyed-move/main.html diff --git a/src/compile/dom/Block.ts b/src/compile/dom/Block.ts index ca3984b5d7..b0879e9d70 100644 --- a/src/compile/dom/Block.ts +++ b/src/compile/dom/Block.ts @@ -177,6 +177,10 @@ export default class Block { this.builders.mount.addLine(`#current = true;`); } + if (!this.builders.mount.isEmpty() && this.builders.outro.isEmpty()) { + this.builders.outro.addLine(`#outrocallback();`); + } + if (!this.builders.outro.isEmpty()) { this.builders.outro.addLine(`#current = false;`); } diff --git a/src/shared/keyed-each.js b/src/shared/keyed-each.js index d3afde60fb..591da14b17 100644 --- a/src/shared/keyed-each.js +++ b/src/shared/keyed-each.js @@ -1,3 +1,5 @@ +import { noop } from './utils.js'; + export function destroyBlock(block, lookup) { block.d(1); lookup[block.key] = null; @@ -47,7 +49,8 @@ export function updateKeyedEach(old_blocks, component, changed, get_key, dynamic var will_move = {}; var did_move = {}; - function insert(block) { + function insert(block, removeFirst) { + if (removeFirst && block.o) block.o(noop); block[intro_method](node, next); lookup[block.key] = block; next = block.first; @@ -74,7 +77,7 @@ export function updateKeyedEach(old_blocks, component, changed, get_key, dynamic } else if (!lookup[new_key] || will_move[new_key]) { - insert(new_block); + insert(new_block, !!lookup[new_key]); } else if (did_move[old_key]) { @@ -82,7 +85,7 @@ export function updateKeyedEach(old_blocks, component, changed, get_key, dynamic } else if (deltas[new_key] > deltas[old_key]) { did_move[new_key] = true; - insert(new_block); + insert(new_block, true); } else { will_move[old_key] = true; diff --git a/test/js/samples/each-block-keyed-animated/expected-bundle.js b/test/js/samples/each-block-keyed-animated/expected-bundle.js index a7f5e22800..ec3d717d9b 100644 --- a/test/js/samples/each-block-keyed-animated/expected-bundle.js +++ b/test/js/samples/each-block-keyed-animated/expected-bundle.js @@ -291,7 +291,8 @@ function updateKeyedEach(old_blocks, component, changed, get_key, dynamic, ctx, var will_move = {}; var did_move = {}; - function insert(block) { + function insert(block, removeFirst) { + if (removeFirst && block.o) block.o(noop); block[intro_method](node, next); lookup[block.key] = block; next = block.first; @@ -318,7 +319,7 @@ function updateKeyedEach(old_blocks, component, changed, get_key, dynamic, ctx, } else if (!lookup[new_key] || will_move[new_key]) { - insert(new_block); + insert(new_block, !!lookup[new_key]); } else if (did_move[old_key]) { @@ -326,7 +327,7 @@ function updateKeyedEach(old_blocks, component, changed, get_key, dynamic, ctx, } else if (deltas[new_key] > deltas[old_key]) { did_move[new_key] = true; - insert(new_block); + insert(new_block, true); } else { will_move[old_key] = true; diff --git a/test/js/samples/each-block-keyed/expected-bundle.js b/test/js/samples/each-block-keyed/expected-bundle.js index 3643c1c059..ec3aff8e03 100644 --- a/test/js/samples/each-block-keyed/expected-bundle.js +++ b/test/js/samples/each-block-keyed/expected-bundle.js @@ -71,7 +71,8 @@ function updateKeyedEach(old_blocks, component, changed, get_key, dynamic, ctx, var will_move = {}; var did_move = {}; - function insert(block) { + function insert(block, removeFirst) { + if (removeFirst && block.o) block.o(noop); block[intro_method](node, next); lookup[block.key] = block; next = block.first; @@ -98,7 +99,7 @@ function updateKeyedEach(old_blocks, component, changed, get_key, dynamic, ctx, } else if (!lookup[new_key] || will_move[new_key]) { - insert(new_block); + insert(new_block, !!lookup[new_key]); } else if (did_move[old_key]) { @@ -106,7 +107,7 @@ function updateKeyedEach(old_blocks, component, changed, get_key, dynamic, ctx, } else if (deltas[new_key] > deltas[old_key]) { did_move[new_key] = true; - insert(new_block); + insert(new_block, true); } else { will_move[old_key] = true; diff --git a/test/runtime/samples/each-block-keyed-component/Todo.html b/test/runtime/samples/each-block-keyed-component/Todo.html new file mode 100644 index 0000000000..18a6961518 --- /dev/null +++ b/test/runtime/samples/each-block-keyed-component/Todo.html @@ -0,0 +1 @@ +

\ No newline at end of file diff --git a/test/runtime/samples/each-block-keyed-component/_config.js b/test/runtime/samples/each-block-keyed-component/_config.js new file mode 100644 index 0000000000..622789d4b7 --- /dev/null +++ b/test/runtime/samples/each-block-keyed-component/_config.js @@ -0,0 +1,41 @@ +export default { + data: { + todos: [ + { id: 123, description: 'one' }, + { id: 234, description: 'two' }, + { id: 345, description: 'three' }, + ] + }, + + html: ` +

1: one

+

2: two

+

3: three

+ `, + + nestedTransitions: true, + + test(assert, component, target) { + const { todos } = component.get(); + + const [p1, p2, p3] = target.querySelectorAll('p'); + + component.set({ + todos: todos.reverse() + }); + + assert.htmlEqual(target.innerHTML, ` +

1: three

+

2: two

+

3: one

+ `); + + const [p4, p5, p6] = target.querySelectorAll('p'); + + assert.equal(p1, p6); + assert.equal(p2, p5); + assert.equal(p3, p4); + + component.destroy(); + } +}; diff --git a/test/runtime/samples/each-block-keyed-component/main.html b/test/runtime/samples/each-block-keyed-component/main.html new file mode 100644 index 0000000000..29686daa4a --- /dev/null +++ b/test/runtime/samples/each-block-keyed-component/main.html @@ -0,0 +1,10 @@ +{#each todos as todo, i (todo.id)} + {i+1}: {todo.description} +{/each} + \ No newline at end of file diff --git a/test/runtime/samples/transition-js-nested-each-keyed-move/Widget.html b/test/runtime/samples/transition-js-nested-each-keyed-move/Widget.html new file mode 100644 index 0000000000..1eff92d871 --- /dev/null +++ b/test/runtime/samples/transition-js-nested-each-keyed-move/Widget.html @@ -0,0 +1 @@ +
{thing}
\ No newline at end of file diff --git a/test/runtime/samples/transition-js-nested-each-keyed-move/_config.js b/test/runtime/samples/transition-js-nested-each-keyed-move/_config.js new file mode 100644 index 0000000000..6ee109a592 --- /dev/null +++ b/test/runtime/samples/transition-js-nested-each-keyed-move/_config.js @@ -0,0 +1,23 @@ +export default { + nestedTransitions: true, + + data: { + things: ['a', 'b', 'c'] + }, + + test(assert, component, target, window, raf) { + assert.htmlEqual(target.innerHTML, ` +
a
+
b
+
c
+ `); + + component.set({ things: ['b', 'c', 'a'] }); + + assert.htmlEqual(target.innerHTML, ` +
b
+
c
+
a
+ `); + }, +}; diff --git a/test/runtime/samples/transition-js-nested-each-keyed-move/main.html b/test/runtime/samples/transition-js-nested-each-keyed-move/main.html new file mode 100644 index 0000000000..965dc3381a --- /dev/null +++ b/test/runtime/samples/transition-js-nested-each-keyed-move/main.html @@ -0,0 +1,9 @@ +{#each things as thing (thing)} + +{/each} + + \ No newline at end of file