mirror of https://github.com/sveltejs/svelte
fix bind:this with elements in each block, add tests for #2806
parent
61eaf2483d
commit
37a4ca920a
@ -0,0 +1,43 @@
|
|||||||
|
import flatten_reference from '../../../utils/flatten_reference';
|
||||||
|
import deindent from '../../../utils/deindent';
|
||||||
|
import Component from '../../../Component';
|
||||||
|
import Block from '../../Block';
|
||||||
|
import Binding from '../../../nodes/Binding';
|
||||||
|
|
||||||
|
export default function bind_this(component: Component, block: Block, binding: Binding, variable: string) {
|
||||||
|
const fn = component.get_unique_name(`${variable}_binding`);
|
||||||
|
|
||||||
|
component.add_var({
|
||||||
|
name: fn,
|
||||||
|
internal: true,
|
||||||
|
referenced: true
|
||||||
|
});
|
||||||
|
|
||||||
|
let lhs;
|
||||||
|
let object;
|
||||||
|
|
||||||
|
if (binding.is_contextual && binding.expression.node.type === 'Identifier') {
|
||||||
|
// bind:x={y} — we can't just do `y = x`, we need to
|
||||||
|
// to `array[index] = x;
|
||||||
|
const { name } = binding.expression.node;
|
||||||
|
const { snippet } = block.bindings.get(name);
|
||||||
|
lhs = snippet;
|
||||||
|
|
||||||
|
// TODO we need to invalidate... something
|
||||||
|
} else {
|
||||||
|
object = flatten_reference(binding.expression.node).name;
|
||||||
|
lhs = component.source.slice(binding.expression.node.start, binding.expression.node.end).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
const contextual_dependencies = [...binding.expression.contextual_dependencies];
|
||||||
|
|
||||||
|
component.partly_hoisted.push(deindent`
|
||||||
|
function ${fn}(${['$$value', ...contextual_dependencies].join(', ')}) {
|
||||||
|
${lhs} = $$value;
|
||||||
|
${object && component.invalidate(object)}
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
block.builders.destroy.add_line(`ctx.${fn}(${['null', ...contextual_dependencies.map(name => `ctx.${name}`)].join(', ')});`);
|
||||||
|
return `@add_binding_callback(() => ctx.${fn}(${[variable, ...contextual_dependencies.map(name => `ctx.${name}`)].join(', ')}));`;
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
<script>
|
||||||
|
export function isFoo() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<p><slot></slot></p>
|
@ -0,0 +1,12 @@
|
|||||||
|
export default {
|
||||||
|
html: ``,
|
||||||
|
|
||||||
|
async test({ assert, component, target }) {
|
||||||
|
component.visible = true;
|
||||||
|
assert.htmlEqual(target.innerHTML, `
|
||||||
|
<p>a</p>
|
||||||
|
`);
|
||||||
|
|
||||||
|
assert.ok(component.items[0].ref.isFoo());
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,13 @@
|
|||||||
|
<script>
|
||||||
|
import Foo from './Foo.svelte';
|
||||||
|
|
||||||
|
export let visible = false;
|
||||||
|
|
||||||
|
export let items = [{ value: 'a', ref: null }];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if visible}
|
||||||
|
{#each items as item}
|
||||||
|
<Foo bind:this={item.ref}>{item.value}</Foo>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
@ -0,0 +1,12 @@
|
|||||||
|
export default {
|
||||||
|
html: ``,
|
||||||
|
|
||||||
|
async test({ assert, component, target }) {
|
||||||
|
component.visible = true;
|
||||||
|
assert.htmlEqual(target.innerHTML, `
|
||||||
|
<div>a</div>
|
||||||
|
`);
|
||||||
|
|
||||||
|
assert.equal(component.items[0].ref, target.querySelector('div'));
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,11 @@
|
|||||||
|
<script>
|
||||||
|
export let visible = false;
|
||||||
|
|
||||||
|
export let items = [{ value: 'a', ref: null }];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if visible}
|
||||||
|
{#each items as item}
|
||||||
|
<div bind:this={item.ref}>{item.value}</div>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
Loading…
Reference in new issue