diff --git a/src/generators/dom/visitors/attributes/addElementBinding.js b/src/generators/dom/visitors/attributes/addElementBinding.js index 7958fc0480..98488351d6 100644 --- a/src/generators/dom/visitors/attributes/addElementBinding.js +++ b/src/generators/dom/visitors/attributes/addElementBinding.js @@ -16,8 +16,9 @@ export default function createBinding ( generator, node, attribute, current, loc const handler = current.getUniqueName( `${local.name}ChangeHandler` ); 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, current, attribute, keypath ) : null; - const value = getBindingValue( generator, local, node, attribute, isMultipleSelect, bindingGroup ); + const value = getBindingValue( generator, local, node, attribute, isMultipleSelect, bindingGroup, type ); const eventName = getBindingEventName( node ); let setter = getSetter({ current, name, context: '__svelte', attribute, dependencies, snippet, value }); @@ -26,7 +27,7 @@ export default function createBinding ( generator, node, attribute, current, loc // special case else if ( attribute.name === 'group' ) { - const type = getStaticAttributeValue( node, 'type' ); + if ( type === 'radio' ) { + setter = deindent` + if ( !${local.name}.checked ) return; + ${setter} + component._bindingGroups[${bindingGroup}].forEach( function ( input ) { + input.checked = false; + });`; + } - if ( type === 'checkbox' ) { - local.init.addLine( - `component._bindingGroups[${bindingGroup}].push( ${local.name} );` - ); + const condition = type === 'checkbox' ? + `~${snippet}.indexOf( ${local.name}.__value )` : + `${local.name}.__value === ${snippet}`; - local.teardown.addBlock( - `component._bindingGroups[${bindingGroup}].splice( component._bindingGroups[${bindingGroup}].indexOf( ${local.name} ), 1 );` - ); + local.init.addLine( + `component._bindingGroups[${bindingGroup}].push( ${local.name} );` + ); - updateElement = `${local.name}.checked = ~${snippet}.indexOf( ${local.name}.__value );`; - } - - else if ( type === 'radio' ) { - throw new Error( 'TODO' ); - } + local.teardown.addBlock( + `component._bindingGroups[${bindingGroup}].splice( component._bindingGroups[${bindingGroup}].indexOf( ${local.name} ), 1 );` + ); - else { - throw new Error( `Unexpected bind:group` ); // TODO catch this in validation with a better error - } + updateElement = `${local.name}.checked = ${condition};`; } // everything else @@ -122,7 +124,7 @@ function getBindingEventName ( node ) { return 'change'; } -function getBindingValue ( generator, local, node, attribute, isMultipleSelect, bindingGroup ) { +function getBindingValue ( generator, local, node, attribute, isMultipleSelect, bindingGroup, type ) { // Alpha + + + + + + +

Beta

`, + + 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, ` + + + + + + +

Alpha

+ ` ); + + component.set({ selected: values[2] }); + assert.equal( inputs[0].checked, false ); + assert.equal( inputs[1].checked, false ); + assert.equal( inputs[2].checked, true ); + + assert.htmlEqual( target.innerHTML, ` + + + + + + +

Gamma

+ ` ); + } +}; diff --git a/test/generator/samples/binding-input-radio-group/main.html b/test/generator/samples/binding-input-radio-group/main.html new file mode 100644 index 0000000000..1b5c1a4d7c --- /dev/null +++ b/test/generator/samples/binding-input-radio-group/main.html @@ -0,0 +1,7 @@ +{{#each values as value}} + +{{/each}} + +

{{selected.name}}

\ No newline at end of file