Repository: sveltejs/svelte (JavaScript)
Date: 2017-04-19 02:12:28+00:00
Task type: Bug Fix

Issue:
Grouped checkbox bindings behaving badly
[REPL](https://svelte.technology/repl?version=1.16.0&gist=067127646900e0e6e979e6ca64f9bbd5). Selecting a checkbox shouldn't deselect others in the group.
Grouped checkbox bindings behaving badly
[REPL](https://svelte.technology/repl?version=1.16.0&gist=067127646900e0e6e979e6ca64f9bbd5). Selecting a checkbox shouldn't deselect others in the group.


Issue discussion:

Solution patch:
diff --git a/src/generators/dom/visitors/Element/Binding.js b/src/generators/dom/visitors/Element/Binding.js
--- a/src/generators/dom/visitors/Element/Binding.js
+++ b/src/generators/dom/visitors/Element/Binding.js
@@ -4,7 +4,7 @@ import getSetter from '../shared/binding/getSetter.js';
 import getStaticAttributeValue from './getStaticAttributeValue.js';
 
 export default function visitBinding ( generator, block, state, node, attribute ) {
-	const { name, keypath } = flattenReference( attribute.value );
+	const { name, keypath, parts } = flattenReference( attribute.value );
 	const { snippet, contexts, dependencies } = block.contextualise( attribute.value );
 
 	if ( dependencies.length > 1 ) throw new Error( 'An unexpected situation arose. Please raise an issue at https://github.com/sveltejs/svelte/issues — thanks!' );
@@ -17,7 +17,7 @@ export default function visitBinding ( generator, block, state, node, attribute
 	const handler = block.getUniqueName( `${state.parentNode}_${eventName}_handler` );
 	const isMultipleSelect = node.name === 'select' && node.attributes.find( attr => attr.name.toLowerCase() === 'multiple' ); // TODO use getStaticAttributeValue
 	const type = getStaticAttributeValue( node, 'type' );
-	const bindingGroup = attribute.name === 'group' ? getBindingGroup( generator, keypath ) : null;
+	const bindingGroup = attribute.name === 'group' ? getBindingGroup( generator, parts.join( '.' ) ) : null;
 	const value = getBindingValue( generator, block, state, node, attribute, isMultipleSelect, bindingGroup, type );
 
 	let setter = getSetter({ block, name, keypath, context: '_svelte', attribute, dependencies, value });


Test patch:
diff --git a/test/runtime/samples/binding-input-checkbox-group-outside-each/_config.js b/test/runtime/samples/binding-input-checkbox-group-outside-each/_config.js
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/binding-input-checkbox-group-outside-each/_config.js
@@ -0,0 +1,78 @@
+const values = [
+	{ name: 'Alpha' },
+	{ name: 'Beta' },
+	{ name: 'Gamma' }
+];
+
+export default {
+	data: {
+		values,
+		selected: [ values[1] ]
+	},
+
+	'skip-ssr': true, // values are rendered as [object Object]
+
+	html: `
+		<label>
+			<input type="checkbox"> Alpha
+		</label>
+
+		<label>
+			<input type="checkbox"> Beta
+		</label>
+
+		<label>
+			<input type="checkbox"> Gamma
+		</label>
+
+		<p>Beta</p>`,
+
+	test ( assert, component, target, window ) {
+		const inputs = target.querySelectorAll( 'input' );
+		assert.equal( inputs[0].checked, false );
+		assert.equal( inputs[1].checked, true );
+		assert.equal( inputs[2].checked, false );
+
+		const event = new window.Event( 'change' );
+
+		inputs[0].checked = true;
+		inputs[0].dispatchEvent( event );
+
+		assert.htmlEqual( target.innerHTML, `
+			<label>
+				<input type="checkbox"> Alpha
+			</label>
+
+			<label>
+				<input type="checkbox"> Beta
+			</label>
+
+			<label>
+				<input type="checkbox"> Gamma
+			</label>
+
+			<p>Alpha, Beta</p>
+		` );
+
+		component.set({ selected: [ values[1], values[2] ] });
+		assert.equal( inputs[0].checked, false );
+		assert.equal( inputs[1].checked, true );
+		assert.equal( inputs[2].checked, true );
+
+		assert.htmlEqual( target.innerHTML, `
+			<label>
+				<input type="checkbox"> Alpha
+			</label>
+
+			<label>
+				<input type="checkbox"> Beta
+			</label>
+
+			<label>
+				<input type="checkbox"> Gamma
+			</label>
+
+			<p>Beta, Gamma</p>
+		` );
+	}
+};
diff --git a/test/runtime/samples/binding-input-checkbox-group-outside-each/main.html b/test/runtime/samples/binding-input-checkbox-group-outside-each/main.html
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/binding-input-checkbox-group-outside-each/main.html
@@ -0,0 +1,13 @@
+<label>
+	<input type="checkbox" value="{{values[0]}}" bind:group='selected' /> {{values[0].name}}
+</label>
+
+<label>
+	<input type="checkbox" value="{{values[1]}}" bind:group='selected' /> {{values[1].name}}
+</label>
+
+<label>
+	<input type="checkbox" value="{{values[2]}}" bind:group='selected' /> {{values[2].name}}
+</label>
+
+<p>{{selected.map( function ( value ) { return value.name; }).join( ', ' ) }}</p>
\ No newline at end of file