Fix: behavior when value is null and add test

when value is null in that selectedIndex set same
as selected but in that that it should be -1.
pull/6874/head
raivaibhav 5 years ago
parent 08fc888515
commit 369468ab8a

@ -137,9 +137,6 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
);
updater = b`${method}(${element.var}, "${name}", ${should_cache ? this.last : value});`;
} else if (property_name) {
block.chunks.hydrate.push(
b`${element.var}.${property_name} = ${init};`
);
const is_selected = property_name === 'selected';
const is_boolean = typeof init.value === 'boolean';
const attr_val = is_boolean ? x`""` : init;
@ -147,6 +144,10 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
block.chunks.hydrate.push(
b`${method}(${element.var}, "${name}", ${attr_val});`
);
} else {
block.chunks.hydrate.push(
b`${element.var}.${property_name} = ${init};`
);
}
updater = block.renderer.options.dev
? b`@prop_dev(${element.var}, "${property_name}", ${should_cache ? this.last : value});`

@ -671,7 +671,8 @@ export default class ElementWrapper extends Wrapper {
}
block.chunks.mount.push(b`
(${data}.multiple ? @select_options : @select_option)(${this.var}, ${data}.value);
('value' in ${data} && !${data}.multiple && @select_option(${this.var}, ${data}.value));
(${data}.multiple && @select_options(${this.var}, ${data}.value));
`);
block.chunks.update.push(b`
if (${block.renderer.dirty(Array.from(dependencies))} && 'value' in ${data}) (${data}.multiple ? @select_options : @select_option)(${this.var}, ${data}.value);;

@ -534,17 +534,15 @@ export function set_style(node, key, value, important) {
}
export function select_option(select, value) {
let count_selected_attr = 0;
for (let i = 0; i < select.options.length; i += 1) {
const option = select.options[i];
if (option.hasAttribute('selected')) count_selected_attr++;
if (option.__value === value) {
option.selected = true;
return;
}
}
if (count_selected_attr === 0) select.selectedIndex = -1; // no option should be selected
select.selectedIndex = -1; // no option should be selected
}
export function select_options(select, value) {
@ -556,6 +554,14 @@ export function select_options(select, value) {
export function select_value(select) {
const selected_option = select.querySelector(':checked') || select.options[0];
if (select.selectedIndex === -1) {
for (let i = 0; i < select.options.length; i += 1) {
const option = select.options[i];
if (option.hasAttribute('selected')) {
return option.__value;
}
}
}
return selected_option && selected_option.__value;
}

@ -0,0 +1,17 @@
// This test make sure if value is bind value is (void 0) then
// it should set to same as the selected option value
export default {
async test({ assert, target }) {
assert.htmlEqual(target.innerHTML, `
<p>selected: c</p>
<select>
<option value='a'>a</option>
<option value='b'>b</option>
<option value='c' selected>c</option>
</select>
<p>selected: c</p>
`);
}
};

@ -0,0 +1,14 @@
<script>
export let selected;
export let o3;
</script>
<p>selected: {selected}</p>
<select bind:value={selected}>
<option>a</option>
<option>b</option>
<option bind:this={o3} selected>c</option>
</select>
<p>selected: {selected}</p>

@ -9,6 +9,8 @@ export default {
</select>
<p>selected: null</p>
<button id="add-attr">add attr</button>
<button id="remove-attr">remove attr</button>
`,
async test({ assert, component, target }) {
@ -22,6 +24,30 @@ export default {
assert.equal(select.selectedIndex, -1);
assert.ok(!options[0].selected);
const addAttrButton = target.querySelector('#add-attr');
addAttrButton.click();
assert.equal(select.value, 'c');
// since svelte don't listen the change, the binded value
// will be null even though there selectedIndex !== -1
assert.htmlEqual(target.innerHTML, `
<p>selected: null</p>
<select>
<option value='a'>a</option>
<option value='b'>b</option>
<option value='c' selected>c</option>
</select>
<p>selected: null</p>
<button id="add-attr">add attr</button>
<button id="remove-attr">remove attr</button>
`);
assert.equal(select.selectedIndex, 2);
assert.ok(options[2].selected);
const removeAttrButton = target.querySelector('#remove-attr');
removeAttrButton.click();
component.selected = 'a'; // first option should now be selected
assert.equal(select.value, 'a');
assert.ok(options[0].selected);
@ -36,6 +62,8 @@ export default {
</select>
<p>selected: a</p>
<button id="add-attr">add attr</button>
<button id="remove-attr">remove attr</button>
`);
component.selected = 'd'; // doesn't match an option
@ -55,6 +83,8 @@ export default {
</select>
<p>selected: d</p>
<button id="add-attr">add attr</button>
<button id="remove-attr">remove attr</button>
`);
}
};

@ -1,6 +1,7 @@
<script>
// set as null so no option will be selected by default
export let selected = null;
export let o3;
</script>
<p>selected: {selected}</p>
@ -8,7 +9,9 @@
<select bind:value={selected}>
<option>a</option>
<option>b</option>
<option>c</option>
<option bind:this={o3}>c</option>
</select>
<p>selected: {selected}</p>
<button id='add-attr' on:click={() => o3.setAttribute('selected', '')}>add attr</button>
<button id='remove-attr' on:click={() => o3.removeAttribute('selected')}>remove attr</button>

@ -0,0 +1,18 @@
export default {
html: `
<p>selected: undefined</p>
<select>
<option value='a'>a</option>
<option value='b'>b</option>
<option value='c' selected>c</option>
</select>
<p>selected: undefined</p>
`,
async test({ assert, target }) {
const select = target.querySelector('select');
assert.equal(select.value, 'c');
}
};

@ -0,0 +1,14 @@
<script>
export let selected;
export let o3;
</script>
<p>selected: {selected}</p>
<select {...{}}>
<option>a</option>
<option>b</option>
<option bind:this={o3} selected>c</option>
</select>
<p>selected: {selected}</p>
Loading…
Cancel
Save