From 806cefe55643e014e760b11a504f505a4316c999 Mon Sep 17 00:00:00 2001 From: Rich-Harris Date: Thu, 2 Mar 2017 10:01:30 -0500 Subject: [PATCH] two-way binding with – can use select.selectedOptions - value = 'selectedOption && selectedOption.__value'; + if ( isMultipleSelect ) { + value = `[].map.call( ${local.name}.selectedOptions, function ( option ) { return option.__value; })`; + } else { + value = 'selectedOption && selectedOption.__value'; + } } else { value = `${local.name}.${attribute.name}`; } @@ -101,7 +105,7 @@ export default function createBinding ( generator, node, attribute, current, loc } // special case - if ( node.name === 'select' ) { + if ( node.name === 'select' && !isMultipleSelect ) { setter = `var selectedOption = ${local.name}.selectedOptions[0] || ${local.name}.options[0];\n` + setter; } @@ -130,19 +134,26 @@ export default function createBinding ( generator, node, attribute, current, loc let updateElement; if ( node.name === 'select' ) { - // TODO select multiple const value = generator.current.getUniqueName( 'value' ); const i = generator.current.getUniqueName( 'i' ); const option = generator.current.getUniqueName( 'option' ); + const ifStatement = isMultipleSelect ? + deindent` + ${option}.selected = ~${value}.indexOf( ${option}.__value );` : + deindent` + if ( ${option}.__value === ${value} ) { + ${option}.selected = true; + break; + }`; + updateElement = deindent` var ${value} = ${contextual ? attribute.value : `root.${attribute.value}`}; + console.log( 'value', ${value} ); for ( var ${i} = 0; ${i} < ${local.name}.options.length; ${i} += 1 ) { var ${option} = ${local.name}.options[${i}]; - if ( ${option}.__value === ${value} ) { - ${option}.selected = true; - break; - } + + ${ifStatement} } `; } else { @@ -164,7 +175,9 @@ export default function createBinding ( generator, node, attribute, current, loc node.initialUpdate = updateElement; local.update.addLine( - `if ( !${local.name}_updating ) ${updateElement}` + `if ( !${local.name}_updating ) { + ${updateElement} + }` ); generator.current.builders.teardown.addLine( deindent` diff --git a/test/generator/binding-select-multiple/_config.js b/test/generator/binding-select-multiple/_config.js new file mode 100644 index 000000000000..89b0da96581f --- /dev/null +++ b/test/generator/binding-select-multiple/_config.js @@ -0,0 +1,68 @@ +export default { + skip: true, // selectedOptions doesn't work in JSDOM??? + + data: { + selected: [ 'two', 'three' ] + }, + + html: ` + + +

selected: two, three

+ `, + + test ( assert, component, target, window ) { + const select = target.querySelector( 'select' ); + const options = [ ...target.querySelectorAll( 'option' ) ]; + + const change = new window.Event( 'change' ); + + options[1].selected = false; + select.dispatchEvent( change ); + + assert.deepEqual( component.get( 'selected' ), [ 'three' ] ); + assert.htmlEqual( target.innerHTML, ` + + +

selected: three

+ ` ); + + options[0].selected = true; + select.dispatchEvent( change ); + + assert.deepEqual( component.get( 'selected' ), [ 'one', 'three' ] ); + assert.htmlEqual( target.innerHTML, ` + + +

selected: one, three

+ ` ); + + component.set({ selected: [ 'one', 'two' ] }); + + assert.ok( options[0].selected ); + assert.ok( options[1].selected ); + assert.ok( !options[2].selected ); + + assert.htmlEqual( target.innerHTML, ` + + +

selected: one, two

+ ` ); + } +}; diff --git a/test/generator/binding-select-multiple/main.html b/test/generator/binding-select-multiple/main.html new file mode 100644 index 000000000000..dc221c13e43f --- /dev/null +++ b/test/generator/binding-select-multiple/main.html @@ -0,0 +1,7 @@ + + +

selected: {{selected.join( ', ' )}}