fix indirect bindings on elements with spreads (#4398)

pull/4404/head
Conduitry 6 years ago committed by GitHub
parent c3232826d4
commit b6d80f485a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,5 +1,9 @@
# Svelte changelog # Svelte changelog
## Unreleased
* Fix indirect bindings involving elements with spreads ([#3680](https://github.com/sveltejs/svelte/issues/3680))
## 3.18.2 ## 3.18.2
* Fix binding to module-level variables ([#4086](https://github.com/sveltejs/svelte/issues/4086)) * Fix binding to module-level variables ([#4086](https://github.com/sveltejs/svelte/issues/4086))

@ -39,20 +39,25 @@ export default class AttributeWrapper {
} }
} }
render(block: Block) { is_indirectly_bound_value() {
const element = this.parent; const element = this.parent;
const name = fix_attribute_casing(this.node.name); const name = fix_attribute_casing(this.node.name);
return name === 'value' &&
const metadata = this.get_metadata();
const is_indirectly_bound_value =
name === 'value' &&
(element.node.name === 'option' || // TODO check it's actually bound (element.node.name === 'option' || // TODO check it's actually bound
(element.node.name === 'input' && (element.node.name === 'input' &&
element.node.bindings.find( element.node.bindings.some(
(binding) => (binding) =>
/checked|group/.test(binding.name) /checked|group/.test(binding.name)
))); )));
}
render(block: Block) {
const element = this.parent;
const name = fix_attribute_casing(this.node.name);
const metadata = this.get_metadata();
const is_indirectly_bound_value = this.is_indirectly_bound_value();
const property_name = is_indirectly_bound_value const property_name = is_indirectly_bound_value
? '__value' ? '__value'

@ -679,10 +679,10 @@ export default class ElementWrapper extends Wrapper {
updates.push(condition ? x`${condition} && ${snippet}` : snippet); updates.push(condition ? x`${condition} && ${snippet}` : snippet);
} else { } else {
const metadata = attr.get_metadata(); const metadata = attr.get_metadata();
const snippet = x`{ ${ const name = attr.is_indirectly_bound_value()
(metadata && metadata.property_name) || ? '__value'
fix_attribute_casing(attr.node.name) : (metadata && metadata.property_name) || fix_attribute_casing(attr.node.name);
}: ${attr.get_value(block)} }`; const snippet = x`{ ${name}: ${attr.get_value(block)} }`;
initial_props.push(snippet); initial_props.push(snippet);
updates.push(condition ? x`${condition} && ${snippet}` : snippet); updates.push(condition ? x`${condition} && ${snippet}` : snippet);

@ -98,7 +98,7 @@ export function set_attributes(node: Element & ElementCSSInlineStyle, attributes
node.removeAttribute(key); node.removeAttribute(key);
} else if (key === 'style') { } else if (key === 'style') {
node.style.cssText = attributes[key]; node.style.cssText = attributes[key];
} else if (descriptors[key] && descriptors[key].set) { } else if (key === '__value' || descriptors[key] && descriptors[key].set) {
node[key] = attributes[key]; node[key] = attributes[key];
} else { } else {
attr(node, key, attributes[key]); attr(node, key, attributes[key]);

@ -0,0 +1,44 @@
export default {
skip_if_ssr: true,
async test({ assert, component, target, window }) {
const event = new window.MouseEvent('click');
const [radio1, radio2, radio3] = target.querySelectorAll('input[type=radio]');
assert.ok(!radio1.checked);
assert.ok(radio2.checked);
assert.ok(!radio3.checked);
component.radio = 'radio1';
assert.ok(radio1.checked);
assert.ok(!radio2.checked);
assert.ok(!radio3.checked);
await radio3.dispatchEvent(event);
assert.equal(component.radio, 'radio3');
assert.ok(!radio1.checked);
assert.ok(!radio2.checked);
assert.ok(radio3.checked);
const [check1, check2, check3] = target.querySelectorAll('input[type=checkbox]');
assert.ok(!check1.checked);
assert.ok(check2.checked);
assert.ok(!check3.checked);
component.check = ['check1', 'check2'];
assert.ok(check1.checked);
assert.ok(check2.checked);
assert.ok(!check3.checked);
await check3.dispatchEvent(event);
assert.deepEqual(component.check, ['check1', 'check2', 'check3']);
assert.ok(check1.checked);
assert.ok(check2.checked);
assert.ok(check3.checked);
}
};

@ -0,0 +1,12 @@
<script>
export let radio = 'radio2';
export let check = ['check2'];
</script>
<input type='radio' bind:group={radio} value='radio1' {...{}}>
<input type='radio' bind:group={radio} value='radio2' {...{}}>
<input type='radio' bind:group={radio} value='radio3' {...{}}>
<input type='checkbox' bind:group={check} value='check1' {...{}}>
<input type='checkbox' bind:group={check} value='check2' {...{}}>
<input type='checkbox' bind:group={check} value='check3' {...{}}>
Loading…
Cancel
Save