mirror of https://github.com/sveltejs/svelte
feat: support `defaultValue` on `<select>` (#18591)
Closes #18447 --------- Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com> Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>pull/18721/head
parent
b433f3cd87
commit
c575b07bca
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': minor
|
||||
---
|
||||
|
||||
feat: support `defaultValue` on `<select>`
|
||||
@ -0,0 +1,96 @@
|
||||
import { test } from '../../test';
|
||||
import { flushSync } from 'svelte';
|
||||
|
||||
export default test({
|
||||
async test({ assert, target }) {
|
||||
/** @param {HTMLSelectElement} select @param {boolean[]} expected */
|
||||
function check(select, expected) {
|
||||
assert.deepEqual(
|
||||
[...select.options].map((option) => option.selected),
|
||||
expected
|
||||
);
|
||||
}
|
||||
|
||||
/** @param {HTMLSelectElement} select @param {number[]} indexes */
|
||||
function select(select, indexes) {
|
||||
for (let i = 0; i < select.options.length; i++) {
|
||||
select.options[i].selected = indexes.includes(i);
|
||||
}
|
||||
select.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
}
|
||||
|
||||
const selects = target.querySelectorAll('select');
|
||||
const reset = /** @type {HTMLInputElement} */ (target.querySelector('input[type=reset]'));
|
||||
/** @param {string} name */
|
||||
const button = (name) => /** @type {HTMLButtonElement} */ (target.querySelector(`.${name}`));
|
||||
|
||||
check(selects[0], [false, true, false]);
|
||||
check(selects[1], [false, false, true]);
|
||||
check(selects[2], [false, true, false]);
|
||||
check(selects[3], [true]);
|
||||
check(selects[4], [false, true]);
|
||||
check(selects[5], [false, true, false]);
|
||||
check(selects[6], [true, false]);
|
||||
check(selects[7], [true, false, true]);
|
||||
check(selects[8], [false, false, true]);
|
||||
|
||||
select(selects[0], [2]);
|
||||
select(selects[1], [0]);
|
||||
select(selects[5], [2]);
|
||||
select(selects[7], [1]);
|
||||
flushSync();
|
||||
|
||||
reset.click();
|
||||
await Promise.resolve();
|
||||
flushSync();
|
||||
check(selects[0], [false, true, false]);
|
||||
check(selects[1], [false, true, false]);
|
||||
check(selects[5], [false, true, false]);
|
||||
check(selects[7], [true, false, true]);
|
||||
|
||||
select(selects[2], [2]);
|
||||
select(selects[5], [2]);
|
||||
button('update').click();
|
||||
flushSync();
|
||||
check(selects[2], [false, false, true]);
|
||||
check(selects[5], [false, false, true]);
|
||||
assert.deepEqual(
|
||||
[...selects[5].options].map((option) => option.defaultSelected),
|
||||
[true, false, false]
|
||||
);
|
||||
|
||||
button('add').click();
|
||||
flushSync();
|
||||
await Promise.resolve();
|
||||
check(selects[3], [true, false]);
|
||||
assert.equal(selects[3].options[1].defaultSelected, true);
|
||||
|
||||
reset.click();
|
||||
await Promise.resolve();
|
||||
flushSync();
|
||||
check(selects[0], [true, false, false]);
|
||||
check(selects[2], [true, false, false]);
|
||||
check(selects[3], [false, true]);
|
||||
check(selects[5], [true, false, false]);
|
||||
|
||||
select(selects[5], [2]);
|
||||
select(selects[7], [1]);
|
||||
button('remove').click();
|
||||
button('clear').click();
|
||||
flushSync();
|
||||
assert.equal(
|
||||
[...selects[5].options].some((option) => option.defaultSelected),
|
||||
false
|
||||
);
|
||||
assert.equal(
|
||||
[...selects[7].options].some((option) => option.defaultSelected),
|
||||
false
|
||||
);
|
||||
|
||||
reset.click();
|
||||
await Promise.resolve();
|
||||
flushSync();
|
||||
check(selects[5], [true, false, false]);
|
||||
check(selects[7], [false, false, false]);
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,79 @@
|
||||
<script>
|
||||
let selected1 = $state();
|
||||
let selected2 = $state('c');
|
||||
let selected3 = $state();
|
||||
let selected4 = $state(['c']);
|
||||
let defaultValue = $state('b');
|
||||
let multipleDefault = $state(/** @type {string[] | undefined} */ (['a', 'c']));
|
||||
let options = $state(['a']);
|
||||
let props = $state({ defaultValue: 'b' });
|
||||
</script>
|
||||
|
||||
<form>
|
||||
<select {defaultValue} bind:value={selected1}>
|
||||
<option value="a">A</option>
|
||||
<option value="b">B</option>
|
||||
<option value="c">C</option>
|
||||
</select>
|
||||
|
||||
<select {defaultValue} bind:value={selected2}>
|
||||
<option value="a">A</option>
|
||||
<option value="b">B</option>
|
||||
<option value="c">C</option>
|
||||
</select>
|
||||
|
||||
<select {defaultValue}>
|
||||
<option value="a">A</option>
|
||||
<option value="b">B</option>
|
||||
<option value="c">C</option>
|
||||
</select>
|
||||
|
||||
<select defaultValue="b">
|
||||
{#each options as option}
|
||||
<option value={option}>{option}</option>
|
||||
{/each}
|
||||
</select>
|
||||
|
||||
<select defaultvalue="b">
|
||||
<option value="a">A</option>
|
||||
<option value="b">B</option>
|
||||
</select>
|
||||
|
||||
<select {...props} bind:value={selected3}>
|
||||
<option value="a">A</option>
|
||||
<option value="b">B</option>
|
||||
<option value="c">C</option>
|
||||
</select>
|
||||
|
||||
<select {...{ defaultValue: 'b' }} defaultValue="a">
|
||||
<option value="a">A</option>
|
||||
<option value="b">B</option>
|
||||
</select>
|
||||
|
||||
<select multiple defaultValue={multipleDefault}>
|
||||
<option value="a">A</option>
|
||||
<option value="b">B</option>
|
||||
<option value="c">C</option>
|
||||
</select>
|
||||
|
||||
<select multiple defaultValue={multipleDefault} bind:value={selected4}>
|
||||
<option value="a">A</option>
|
||||
<option value="b">B</option>
|
||||
<option value="c">C</option>
|
||||
</select>
|
||||
|
||||
<input type="reset" value="Reset" />
|
||||
<button
|
||||
type="button"
|
||||
class="update"
|
||||
onclick={() => {
|
||||
defaultValue = 'a';
|
||||
props.defaultValue = 'a';
|
||||
}}>Update defaults</button
|
||||
>
|
||||
<button type="button" class="add" onclick={() => options.push('b')}>Add option</button>
|
||||
<button type="button" class="remove" onclick={() => delete props.defaultValue}>Remove default</button>
|
||||
<button type="button" class="clear" onclick={() => (multipleDefault = undefined)}>Clear defaults</button>
|
||||
</form>
|
||||
|
||||
<p>{selected1} {selected2} {selected3} {selected4.join(',')}</p>
|
||||
@ -0,0 +1,25 @@
|
||||
<select>
|
||||
<option value="a">A</option>
|
||||
<option selected="" value="b">B</option>
|
||||
</select>
|
||||
<select>
|
||||
<option value="a">A</option>
|
||||
<option selected="" value="b">B</option>
|
||||
</select>
|
||||
<select>
|
||||
<option selected="" value="a">A</option>
|
||||
<option value="b">B</option>
|
||||
</select>
|
||||
<select multiple="">
|
||||
<option selected="" value="a">A</option>
|
||||
<option value="b">B</option>
|
||||
<option selected="" value="c">C</option>
|
||||
</select>
|
||||
<select>
|
||||
<option value="a">A</option>
|
||||
<option selected="" value="b">B</option>
|
||||
</select>
|
||||
<select>
|
||||
<option selected="" value="a">A</option>
|
||||
<option value="b">B</option>
|
||||
</select>
|
||||
@ -0,0 +1,34 @@
|
||||
<script>
|
||||
const props = { defaultValue: 'b' };
|
||||
</script>
|
||||
|
||||
<select defaultValue="b">
|
||||
<option value="a">A</option>
|
||||
<option value="b">B</option>
|
||||
</select>
|
||||
|
||||
<select {...props}>
|
||||
<option value="a">A</option>
|
||||
<option value="b">B</option>
|
||||
</select>
|
||||
|
||||
<select defaultValue="b" value="a">
|
||||
<option value="a">A</option>
|
||||
<option value="b">B</option>
|
||||
</select>
|
||||
|
||||
<select multiple="" defaultValue={['a', 'c']}>
|
||||
<option value="a">A</option>
|
||||
<option value="b">B</option>
|
||||
<option value="c">C</option>
|
||||
</select>
|
||||
|
||||
<select defaultvalue="b">
|
||||
<option value="a">A</option>
|
||||
<option value="b">B</option>
|
||||
</select>
|
||||
|
||||
<select {...{ defaultValue: 'b' }} defaultValue="a">
|
||||
<option value="a">A</option>
|
||||
<option value="b">B</option>
|
||||
</select>
|
||||
Loading…
Reference in new issue