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
pull/1729/head
Jacob Wright 7 years ago
parent a4d412fb53
commit 2aba4335b0

@ -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;`);
}

@ -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;

@ -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;

@ -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;

@ -0,0 +1,41 @@
export default {
data: {
todos: [
{ id: 123, description: 'one' },
{ id: 234, description: 'two' },
{ id: 345, description: 'three' },
]
},
html: `
<p>1: one</p>
<p>2: two</p>
<p>3: three</p>
`,
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, `
<p>1: three</p>
<p>2: two</p>
<p>3: one</p>
`);
const [p4, p5, p6] = target.querySelectorAll('p');
assert.equal(p1, p6);
assert.equal(p2, p5);
assert.equal(p3, p4);
component.destroy();
}
};

@ -0,0 +1,10 @@
{#each todos as todo, i (todo.id)}
<Todo>{i+1}: {todo.description}</Todo>
{/each}
<script>
export default {
components: {
Todo: './Todo.html'
}
};
</script>

@ -0,0 +1,23 @@
export default {
nestedTransitions: true,
data: {
things: ['a', 'b', 'c']
},
test(assert, component, target, window, raf) {
assert.htmlEqual(target.innerHTML, `
<div>a</div>
<div>b</div>
<div>c</div>
`);
component.set({ things: ['b', 'c', 'a'] });
assert.htmlEqual(target.innerHTML, `
<div>b</div>
<div>c</div>
<div>a</div>
`);
},
};

@ -0,0 +1,9 @@
{#each things as thing (thing)}
<Widget :thing/>
{/each}
<script>
export default {
components: { Widget: './Widget.html' }
};
</script>
Loading…
Cancel
Save