0
0
mirror of https://github.com/sveltejs/svelte.git synced 2024-12-01 17:30:59 +01:00

deep store bindings

This commit is contained in:
Richard Harris 2019-03-09 16:57:02 -05:00
parent a203bfd071
commit 093cc0f83e
2 changed files with 51 additions and 19 deletions

View File

@ -213,6 +213,12 @@ function getBindingGroup(renderer: Renderer, value: Node) {
return index;
}
function mutate_store(store, value, tail) {
return tail
? `${store}.update($$value => ($$value${tail} = ${value}, $$value));`
: `${store}.set(${value});`;
}
function getEventHandler(
binding: BindingWrapper,
renderer: Renderer,
@ -223,36 +229,26 @@ function getEventHandler(
const value = getValueFromDom(renderer, binding.parent, binding);
const store = binding.object[0] === '$' ? binding.object.slice(1) : null;
if (store && binding.node.expression.node.type === 'MemberExpression') {
// TODO is there a way around this? Mutating an object doesn't work,
// because stores check for referential equality (i.e. immutable data).
// But we can't safely or easily clone objects. So for now, we bail
renderer.component.error(binding.node.expression.node.property, {
code: 'invalid-store-binding',
message: 'Cannot bind to a nested property of a store'
});
let tail = '';
if (binding.node.expression.node.type === 'MemberExpression') {
const { start, end } = get_tail(binding.node.expression.node);
tail = renderer.component.source.slice(start, end);
}
if (binding.node.isContextual) {
let tail = '';
if (binding.node.expression.node.type === 'MemberExpression') {
const { start, end } = get_tail(binding.node.expression.node);
tail = renderer.component.source.slice(start, end);
}
const { object, property, snippet } = block.bindings.get(name);
return {
usesContext: true,
mutation: store
? `${store}.set(${value});`
? mutate_store(store, value, tail)
: `${snippet}${tail} = ${value};`,
contextual_dependencies: new Set([object, property])
};
}
const mutation = store
? `${store}.set(${value});`
? mutate_store(store, value, tail)
: `${snippet} = ${value};`;
if (binding.node.expression.node.type === 'MemberExpression') {

View File

@ -1,5 +1,41 @@
export default {
error(assert, err) {
assert.equal(err.message, `Cannot bind to a nested property of a store`);
}
html: `
<input>
<p>hello world</p>
`,
ssrHtml: `
<input value="world">
<p>hello world</p>
`,
async test({ assert, component, target, window }) {
const input = target.querySelector('input');
assert.equal(input.value, 'world');
const event = new window.Event('input');
const names = [];
const unsubscribe = component.user.subscribe(user => {
names.push(user.name);
});
input.value = 'everybody';
await input.dispatchEvent(event);
assert.htmlEqual(target.innerHTML, `
<input>
<p>hello everybody</p>
`);
await component.user.set({ name: 'goodbye' });
assert.equal(input.value, 'goodbye');
assert.htmlEqual(target.innerHTML, `
<input>
<p>hello goodbye</p>
`);
assert.deepEqual(names, ['world', 'everybody', 'goodbye']);
unsubscribe();
},
};