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