mirror of https://github.com/sveltejs/svelte
feat: allow dynamic `type` attribute with `bind:value` (#10608)
Since these all share the same underlying small runtime code, there's no reason anymore to not allow it. closes #10256 closes #3921pull/10614/head
parent
db0b802fc2
commit
506196b72b
@ -0,0 +1,5 @@
|
||||
---
|
||||
"svelte": patch
|
||||
---
|
||||
|
||||
feat: allow dynamic `type` attribute with `bind:value`
|
@ -0,0 +1,72 @@
|
||||
import { tick } from 'svelte';
|
||||
import { test, ok } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `
|
||||
<input type=text>
|
||||
<input type=text>
|
||||
<p>x / y</p>
|
||||
|
||||
<button>change to text</button>
|
||||
<button>change to number</button>
|
||||
<button>change to range</button>
|
||||
`,
|
||||
ssrHtml: `
|
||||
<input type=text value=x>
|
||||
<input type=text value=y>
|
||||
<p>x / y</p>
|
||||
|
||||
<button>change to text</button>
|
||||
<button>change to number</button>
|
||||
<button>change to range</button>
|
||||
`,
|
||||
async test({ assert, target }) {
|
||||
const [in1, in2] = target.querySelectorAll('input');
|
||||
const [btn1, btn2, btn3] = target.querySelectorAll('button');
|
||||
const p = target.querySelector('p');
|
||||
ok(p);
|
||||
|
||||
in1.value = '0';
|
||||
in2.value = '1';
|
||||
in1.dispatchEvent(new window.Event('input', { bubbles: true }));
|
||||
in2.dispatchEvent(new window.Event('input', { bubbles: true }));
|
||||
await tick();
|
||||
btn2?.click();
|
||||
await tick();
|
||||
assert.htmlEqual(p.innerHTML, '0 / 1');
|
||||
|
||||
in1.stepUp();
|
||||
in1.dispatchEvent(new window.Event('input', { bubbles: true }));
|
||||
in2.stepUp();
|
||||
in2.dispatchEvent(new window.Event('input', { bubbles: true }));
|
||||
await tick();
|
||||
assert.htmlEqual(p.innerHTML, '1 / 2');
|
||||
|
||||
btn1?.click();
|
||||
await tick();
|
||||
try {
|
||||
in1.stepUp();
|
||||
assert.fail();
|
||||
} catch (e) {
|
||||
// expected
|
||||
}
|
||||
|
||||
btn3?.click();
|
||||
await tick();
|
||||
in1.stepUp();
|
||||
in1.dispatchEvent(new window.Event('input', { bubbles: true }));
|
||||
in2.stepUp();
|
||||
in2.dispatchEvent(new window.Event('input', { bubbles: true }));
|
||||
await tick();
|
||||
assert.htmlEqual(p.innerHTML, '2 / 3');
|
||||
|
||||
btn1?.click();
|
||||
await tick();
|
||||
in1.value = 'a';
|
||||
in2.value = 'b';
|
||||
in1.dispatchEvent(new window.Event('input', { bubbles: true }));
|
||||
in2.dispatchEvent(new window.Event('input', { bubbles: true }));
|
||||
await tick();
|
||||
assert.htmlEqual(p.innerHTML, 'a / b');
|
||||
}
|
||||
});
|
@ -0,0 +1,14 @@
|
||||
<script>
|
||||
let dynamic = $state('x');
|
||||
let spread = $state('y');
|
||||
let inputType = $state('text');
|
||||
let props = $derived({type: inputType});
|
||||
</script>
|
||||
|
||||
<input bind:value={dynamic} type={inputType}>
|
||||
<input bind:value={spread} {...props}>
|
||||
<p>{dynamic} / {spread}</p>
|
||||
|
||||
<button onclick={() => inputType = 'text'}>change to text</button>
|
||||
<button onclick={() => inputType = 'number'}>change to number</button>
|
||||
<button onclick={() => inputType = 'range'}>change to range</button>
|
@ -1,14 +0,0 @@
|
||||
[
|
||||
{
|
||||
"code": "invalid-type-attribute",
|
||||
"message": "'type' attribute must be a static text value if input uses two-way binding",
|
||||
"start": {
|
||||
"line": 6,
|
||||
"column": 24
|
||||
},
|
||||
"end": {
|
||||
"line": 6,
|
||||
"column": 40
|
||||
}
|
||||
}
|
||||
]
|
@ -1,6 +0,0 @@
|
||||
<script>
|
||||
let foo;
|
||||
let inputType;
|
||||
</script>
|
||||
|
||||
<input bind:value={foo} type={inputType}>
|
Loading…
Reference in new issue