fix: ensure select value is updated upon select element removal (#10846)

* fix: ensure select value is updated upon select element removal

* lint

* lol
pull/10847/head
Dominic Gannaway 4 months ago committed by GitHub
parent 682f4a6513
commit c564c77199
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
"svelte": patch
---
fix: ensure select value is updated upon select element removal

@ -91,6 +91,28 @@ export function bind_select_value(select, get_value, update) {
select.__value = value;
mounting = false;
});
// If one of the options gets removed from the DOM, the value might have changed
effect(() => {
var observer = new MutationObserver(() => {
// @ts-ignore
var value = select.__value;
select_option(select, value, mounting);
/** @type {HTMLOptionElement | null} */
var selected_option = select.querySelector(':checked');
if (selected_option === null || get_option_value(selected_option) !== value) {
update('');
}
});
observer.observe(select, {
childList: true
});
return () => {
observer.disconnect();
};
});
}
/**

@ -0,0 +1,34 @@
import { ok, test } from '../../test';
// test select binding behavior when a selected option is removed
export default test({
skip_if_ssr: 'permanent',
html: `<p>selected: a</p><select><option value="a">a</option><option value="b">b</option><option value="c">c</option></select>`,
async test({ assert, component, target }) {
const select = target.querySelector('select');
ok(select);
const options = target.querySelectorAll('option');
// first option should be selected by default since no value was bound
assert.equal(component.selected, 'a');
assert.equal(select.value, 'a');
assert.ok(options[0].selected);
// remove the selected item, so the bound value no longer matches anything
component.items = ['b', 'c'];
// There's a MutationObserver
await Promise.resolve();
// now no option should be selected
assert.equal(select.value, '');
assert.equal(select.selectedIndex, -1);
assert.htmlEqual(
target.innerHTML,
`<p>selected:</p><select><option value="b">b</option><option value="c">c</option></select>`
);
}
});

@ -0,0 +1,12 @@
<script>
export let selected;
export let items = ['a', 'b', 'c'];
</script>
<p>selected: {selected}</p>
<select bind:value={selected}>
{#each items as letter}
<option>{letter}</option>
{/each}
</select>
Loading…
Cancel
Save