maintain context for keyed each (#5840)

pull/5849/head
Tan Li Hau 5 years ago committed by GitHub
parent a41c7644e6
commit 63669330f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4,6 +4,7 @@
* Fix location of automatically declared reactive variables ([#5749](https://github.com/sveltejs/svelte/issues/5749))
* Warn when using `className` or `htmlFor` attributes ([#5777](https://github.com/sveltejs/svelte/issues/5777))
* Fix checkbox `bind:group` in keyed `{#each}` where the array can be reordered ([#5779](https://github.com/sveltejs/svelte/issues/5779))
* Fix checkbox `bind:group` in nested `{#each}` contexts ([#5811](https://github.com/sveltejs/svelte/issues/5811))
* Add graphics roles as known ARIA roles ([#5822](https://github.com/sveltejs/svelte/pull/5822))

@ -447,6 +447,8 @@ export default class EachBlockWrapper extends Wrapper {
: '@destroy_block';
if (this.dependencies.size) {
this.block.maintain_context = true;
this.updates.push(b`
const ${this.vars.each_block_value} = ${snippet};
${this.renderer.options.dev && b`@validate_each_argument(${this.vars.each_block_value});`}

@ -851,7 +851,21 @@ export default class ElementWrapper extends Wrapper {
${outro && b`@add_transform(${this.var}, ${rect});`}
`);
const params = this.node.animation.expression ? this.node.animation.expression.manipulate(block) : x`{}`;
let params;
if (this.node.animation.expression) {
params = this.node.animation.expression.manipulate(block);
if (this.node.animation.expression.dynamic_dependencies().length) {
// if `params` is dynamic, calculate params ahead of time in the `.r()` method
const params_var = block.get_unique_name('params');
block.add_variable(params_var);
block.chunks.measure.push(b`${params_var} = ${params};`);
params = params_var;
}
} else {
params = x`{}`;
}
const name = this.renderer.reference(this.node.animation.name);

@ -43,7 +43,8 @@ function create_each_block(key_1, ctx) {
insert(target, div, anchor);
append(div, t);
},
p(ctx, dirty) {
p(new_ctx, dirty) {
ctx = new_ctx;
if (dirty & /*things*/ 1 && t_value !== (t_value = /*thing*/ ctx[1].name + "")) set_data(t, t_value);
},
r() {

@ -39,7 +39,8 @@ function create_each_block(key_1, ctx) {
insert(target, div, anchor);
append(div, t);
},
p(ctx, dirty) {
p(new_ctx, dirty) {
ctx = new_ctx;
if (dirty & /*things*/ 1 && t_value !== (t_value = /*thing*/ ctx[1].name + "")) set_data(t, t_value);
},
d(detaching) {

@ -18,7 +18,7 @@ export default {
`,
test({ assert, component, target, window, raf }) {
let divs = document.querySelectorAll('div');
let divs = window.document.querySelectorAll('div');
divs.forEach(div => {
div.getBoundingClientRect = function() {
const index = [...this.parentNode.children].indexOf(this);
@ -41,7 +41,7 @@ export default {
{ id: 1, name: 'a' }
];
divs = document.querySelectorAll('div');
divs = window.document.querySelectorAll('div');
assert.equal(divs[0].dy, 120);
assert.equal(divs[4].dy, -120);
@ -56,5 +56,29 @@ export default {
raf.tick(150);
assert.equal(divs[0].dy, 0);
assert.equal(divs[4].dy, 0);
component.things = [
{ id: 1, name: 'a' },
{ id: 2, name: 'b' },
{ id: 3, name: 'c' },
{ id: 4, name: 'd' },
{ id: 5, name: 'e' }
];
divs = document.querySelectorAll('div');
assert.equal(divs[0].dy, 120);
assert.equal(divs[4].dy, -120);
raf.tick(200);
assert.equal(divs[0].dy, 108);
assert.equal(divs[4].dy, -60);
raf.tick(250);
assert.equal(divs[0].dy, 48);
assert.equal(divs[4].dy, 0);
raf.tick(300);
assert.equal(divs[0].dy, 0);
assert.equal(divs[4].dy, 0);
}
};

@ -0,0 +1,65 @@
export default {
html: `
<label><input type="checkbox" value="Vanilla"> Vanilla</label>
<label><input type="checkbox" value="Strawberry"> Strawberry</label>
<label><input type="checkbox" value="Chocolate"> Chocolate</label>
<label><input type="checkbox" value="Lemon"> Lemon</label>
<label><input type="checkbox" value="Coconut"> Coconut</label>
`,
async test({ assert, target, window }) {
const [input1, input2, input3, input4, input5] = target.querySelectorAll('input');
const event = new window.Event('change');
input3.checked = true;
await input3.dispatchEvent(event);
assert.htmlEqual(target.innerHTML, `
<label><input type="checkbox" value="Chocolate"> Chocolate</label>
<label><input type="checkbox" value="Vanilla"> Vanilla</label>
<label><input type="checkbox" value="Strawberry"> Strawberry</label>
<label><input type="checkbox" value="Lemon"> Lemon</label>
<label><input type="checkbox" value="Coconut"> Coconut</label>
`);
assert.equal(input1.checked, false);
assert.equal(input2.checked, false);
assert.equal(input3.checked, true);
assert.equal(input4.checked, false);
assert.equal(input5.checked, false);
input4.checked = true;
await input4.dispatchEvent(event);
assert.htmlEqual(target.innerHTML, `
<label><input type="checkbox" value="Chocolate"> Chocolate</label>
<label><input type="checkbox" value="Lemon"> Lemon</label>
<label><input type="checkbox" value="Vanilla"> Vanilla</label>
<label><input type="checkbox" value="Strawberry"> Strawberry</label>
<label><input type="checkbox" value="Coconut"> Coconut</label>
`);
assert.equal(input1.checked, false);
assert.equal(input2.checked, false);
assert.equal(input3.checked, true);
assert.equal(input4.checked, true);
assert.equal(input5.checked, false);
input3.checked = false;
await input3.dispatchEvent(event);
assert.htmlEqual(target.innerHTML, `
<label><input type="checkbox" value="Lemon"> Lemon</label>
<label><input type="checkbox" value="Chocolate"> Chocolate</label>
<label><input type="checkbox" value="Vanilla"> Vanilla</label>
<label><input type="checkbox" value="Strawberry"> Strawberry</label>
<label><input type="checkbox" value="Coconut"> Coconut</label>
`);
assert.equal(input1.checked, false);
assert.equal(input2.checked, false);
assert.equal(input3.checked, false);
assert.equal(input4.checked, true);
assert.equal(input5.checked, false);
}
};

@ -0,0 +1,21 @@
<script>
let flavours = [
'Vanilla',
'Strawberry',
'Chocolate',
'Lemon',
'Coconut'
];
let choices = [];
// Put choices first by sorting
$: flavours = flavours.sort((a, b) => choices.includes(b) - choices.includes(a));
</script>
{#each flavours as flavour (flavour)}
<label>
<input type=checkbox bind:group={choices} value={flavour}>
{flavour}
</label>
{/each}
Loading…
Cancel
Save