Skip to content

Commit

Permalink
Merge pull request #521 from sveltejs/select-change-handler
Browse files Browse the repository at this point in the history
[WIP] Fix select change handler
  • Loading branch information
Rich-Harris authored Apr 25, 2017
2 parents fbfd011 + 1cd2287 commit 09b1635
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 17 deletions.
32 changes: 15 additions & 17 deletions src/generators/dom/visitors/Element/Element.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,19 @@ export default function visitElement ( generator, block, state, node ) {
block.builders.create.addLine( `${generator.helper( 'setAttribute' )}( ${name}, '${generator.cssId}', '' );` );
}

let selectValueAttribute;

node.attributes
.sort( ( a, b ) => order[ a.type ] - order[ b.type ] )
.forEach( attribute => {
// <select> value attributes are an annoying special case — it must be handled
// *after* its children have been updated
if ( ( attribute.type === 'Attribute' || attribute.type === 'Binding' ) && attribute.name === 'value' && node.name === 'select' ) {
selectValueAttribute = attribute;
return;
}

visitors[ attribute.type ]( generator, block, childState, node, attribute );
});
function visitAttributes () {
node.attributes
.sort( ( a, b ) => order[ a.type ] - order[ b.type ] )
.forEach( attribute => {
visitors[ attribute.type ]( generator, block, childState, node, attribute );
});
}

if ( node.name !== 'select' ) {
// <select> value attributes are an annoying special case — it must be handled
// *after* its children have been updated
visitAttributes();
}

// special case – bound <option> without a value attribute
if ( node.name === 'option' && !node.attributes.find( attribute => attribute.type === 'Attribute' && attribute.name === 'value' ) ) { // TODO check it's bound
Expand Down Expand Up @@ -116,9 +115,8 @@ export default function visitElement ( generator, block, state, node ) {
block.builders.update.addLine( node.lateUpdate );
}

if ( selectValueAttribute ) {
const visitor = selectValueAttribute.type === 'Attribute' ? visitAttribute : visitBinding;
visitor( generator, block, childState, node, selectValueAttribute );
if ( node.name === 'select' ) {
visitAttributes();
}

if ( node.initialUpdate ) {
Expand Down
24 changes: 24 additions & 0 deletions test/runtime/samples/select-change-handler/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export default {
skip: true, // JSDOM

data: {
options: [ { id: 'a' }, { id: 'b' }, { id: 'c' } ],
selected: 'b'
},

test ( assert, component, target, window ) {
const select = target.querySelector( 'select' );
assert.equal( select.value, 'b' );

const event = new window.Event( 'change' );

select.value = 'c';
select.dispatchEvent( event );

assert.equal( select.value, 'c' );
assert.equal( component.get( 'lastChangedTo' ), 'c' );
assert.equal( component.get( 'selected' ), 'c' );

component.destroy();
}
};
15 changes: 15 additions & 0 deletions test/runtime/samples/select-change-handler/main.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<select bind:value="selected" on:change="updateLastChangedTo(selected)">
{{#each options as option}}
<option value="{{option.id}}">{{option.id}}</option>
{{/each}}
</select>

<script>
export default {
methods: {
updateLastChangedTo(result) {
this.set({ lastChangedTo: result });
}
}
};
</script>

0 comments on commit 09b1635

Please sign in to comment.