Skip to content

Commit 012289a

Browse files
authored
Merge pull request #1490 from sveltejs/gh-1489
fix dynamic component bindings (#1489)
2 parents 80077c1 + df60585 commit 012289a

File tree

5 files changed

+88
-6
lines changed

5 files changed

+88
-6
lines changed

src/compile/nodes/Component.ts

+14-6
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ export default class Component extends Node {
290290
}
291291

292292
statements.push(deindent`
293-
if (${binding.prop} in ${binding.obj}) {
293+
if (${binding.value.snippet} !== void 0) {
294294
${name_initial_data}.${binding.name} = ${binding.value.snippet};
295295
${name_updating}.${binding.name} = true;
296296
}`
@@ -304,7 +304,7 @@ export default class Component extends Node {
304304
updates.push(deindent`
305305
if (!${name_updating}.${binding.name} && ${[...binding.value.dependencies].map((dependency: string) => `changed.${dependency}`).join(' || ')}) {
306306
${name_changes}.${binding.name} = ${binding.value.snippet};
307-
${name_updating}.${binding.name} = true;
307+
${name_updating}.${binding.name} = ${binding.value.snippet} !== void 0;
308308
}
309309
`);
310310
});
@@ -318,7 +318,7 @@ export default class Component extends Node {
318318

319319
// TODO use component.on('state', ...) instead of _bind
320320
componentInitProperties.push(deindent`
321-
_bind: function(changed, childState) {
321+
_bind(changed, childState) {
322322
var ${initialisers};
323323
${builder}
324324
${hasStoreBindings && `#component.store.set(newStoreState);`}
@@ -328,7 +328,7 @@ export default class Component extends Node {
328328
`);
329329

330330
beforecreate = deindent`
331-
#component.root._beforecreate.push(function() {
331+
#component.root._beforecreate.push(() => {
332332
${name}._bind({ ${this.bindings.map(b => `${b.name}: 1`).join(', ')} }, ${name}.get());
333333
});
334334
`;
@@ -406,6 +406,14 @@ export default class Component extends Node {
406406
407407
if (${switch_value}) {
408408
${name} = new ${switch_value}(${switch_props}(ctx));
409+
410+
${this.bindings.length > 0 && deindent`
411+
#component.root._beforecreate.push(() => {
412+
const changed = {};
413+
${this.bindings.map(binding => deindent`
414+
if (${binding.value.snippet} === void 0) changed.${binding.name} = 1;`)}
415+
${name}._bind(changed, ${name}.get());
416+
});`}
409417
${name}._fragment.c();
410418
411419
${this.children.map(child => child.remount(name))}
@@ -554,8 +562,8 @@ export default class Component extends Node {
554562

555563
const expression = (
556564
this.name === 'svelte:self' ? this.compiler.name :
557-
isDynamicComponent ? `((${this.expression.snippet}) || @missingComponent)` :
558-
`%components-${this.name}`
565+
(isDynamicComponent ? `((${this.expression.snippet}) || @missingComponent)` :
566+
`%components-${this.name}`)
559567
);
560568

561569
this.bindings.forEach(binding => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<p>green {foo}</p>
2+
3+
<script>
4+
export default {
5+
data() {
6+
return {
7+
foo: 'green'
8+
};
9+
}
10+
};
11+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<p>red {foo}</p>
2+
3+
<script>
4+
export default {
5+
data() {
6+
return {
7+
foo: 'red'
8+
};
9+
}
10+
};
11+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
export default {
2+
data: {
3+
x: true
4+
},
5+
6+
html: `
7+
<p>parent green</p>
8+
<p>green green</p>
9+
`,
10+
11+
test(assert, component, target) {
12+
// TODO replace this with component.set({ foo: undefined }) post-#1488
13+
// component.set({ foo: undefined });
14+
// delete component._state.foo;
15+
16+
component.set({
17+
x: false,
18+
foo: undefined
19+
});
20+
21+
assert.htmlEqual(target.innerHTML, `
22+
<p>parent red</p>
23+
<p>red red</p>
24+
`);
25+
26+
component.set({
27+
x: true,
28+
foo: undefined
29+
});
30+
31+
assert.htmlEqual(target.innerHTML, `
32+
<p>parent green</p>
33+
<p>green green</p>
34+
`);
35+
}
36+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<p>parent {foo}</p>
2+
<svelte:component this="{x ? Green : Red}" bind:foo />
3+
4+
<script>
5+
import Green from './Green.html';
6+
import Red from './Red.html';
7+
8+
export default {
9+
data() {
10+
return {
11+
Green,
12+
Red
13+
};
14+
}
15+
};
16+
</script>

0 commit comments

Comments
 (0)