Skip to content

Commit

Permalink
Merge pull request #304 from sveltejs/gh-301
Browse files Browse the repository at this point in the history
Initialise <select> elements with two-way binding
  • Loading branch information
Rich-Harris authored Feb 27, 2017
2 parents ce1916f + f317568 commit 0d29d46
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 8 deletions.
4 changes: 4 additions & 0 deletions src/generators/dom/visitors/Element.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ export default {
return Component.leave( generator, node );
}

if ( node.initialUpdate ) {
generator.current.builders.init.addBlock( node.initialUpdate );
}

generator.pop();
}
};
32 changes: 24 additions & 8 deletions src/generators/dom/visitors/attributes/binding/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,27 @@ export default function createBinding ( generator, node, attribute, current, loc
}
` );
} else {
const updateElement = `${local.name}.${attribute.name} = ${contextual ? attribute.value : `root.${attribute.value}`}`;
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' );

updateElement = deindent`
var ${value} = ${contextual ? attribute.value : `root.${attribute.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;
}
}
`;
} else {
updateElement = `${local.name}.${attribute.name} = ${contextual ? attribute.value : `root.${attribute.value}`};`;
}

generator.uses.addEventListener = true;
generator.uses.removeEventListener = true;
Expand All @@ -130,20 +150,16 @@ export default function createBinding ( generator, node, attribute, current, loc
}
addEventListener( ${local.name}, '${eventName}', ${handler} );
${updateElement};
` );

node.initialUpdate = updateElement;

local.update.addLine(
`if ( !${local.name}_updating ) ${updateElement};`
`if ( !${local.name}_updating ) ${updateElement}`
);

generator.current.builders.teardown.addLine( deindent`
removeEventListener( ${local.name}, '${eventName}', ${handler} );
` );
}

if ( node.name === 'select' ) {
generator.hasComplexBindings = true;
local.init.addLine( `component._bindings.push( ${handler} )` );
}
}
29 changes: 29 additions & 0 deletions test/generator/binding-select-initial-value/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export default {
skip: true, // selectedOptions doesn't work in JSDOM???

html: `
<p>selected: b</p>
<select>
<option>a</option>
<option>b</option>
<option>c</option>
</select>
<p>selected: b</p>
`,

data: {
selected: 'b'
},

test ( assert, component, target ) {
const select = target.querySelector( 'select' );
const options = [ ...target.querySelectorAll( 'option' ) ];

assert.equal( select.value, 'b' );
assert.ok( options[1].selected );

component.teardown();
}
};
9 changes: 9 additions & 0 deletions test/generator/binding-select-initial-value/main.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<p>selected: {{selected}}</p>

<select bind:value='selected'>
<option value="a">a</option>
<option value="b">b</option>
<option value="c">c</option>
</select>

<p>selected: {{selected}}</p>

0 comments on commit 0d29d46

Please sign in to comment.