error: 'type' attribute cannot be dynamic if input uses two-way binding
error: 'type' attribute cannot be dynamic if input uses two-way binding
我试图为我的项目创建一个 Input
组件。我想在 input
元素
上动态设置类型属性
但是当我在 input
上动态设置类型属性时,我得到错误提示
'type' attribute cannot be dynamic if input uses two-way binding
所以有什么解决方法可以动态设置类型属性而不会丢失双向绑定
Input.svelte
<script>
export let placeholder = "";
export let label = "";
export let description = "";
export let value = "";
export let type = "text";
</script>
<div class="container">
<label>{label}</label>
<input {type} bind:value {placeholder} />
<p>{description}</p>
</div>
type
双向绑定必须是静态的原因是 Svelte 生成的代码对于不同类型的输入是不同的。例如,number
和 range
输入必须将其值强制转换为数字,一些输入需要 change
事件侦听器而不是 input
事件,反之亦然,等等。
但是您可以手动执行生成的代码会执行的相同操作 — 添加一个反映状态的事件侦听器:
<script>
export let placeholder = "";
export let label = "";
export let description = "";
export let value = "";
export let type = "text";
const handleInput = e => {
// in here, you can switch on type and implement
// whatever behaviour you need
value = type.match(/^(number|range)$/)
? +e.target.value
: e.target.value;
};
</script>
<div class="container">
<label>{label}</label>
<input {type} {value} {placeholder} on:input={handleInput} />
<p>{description}</p>
</div>
一个简单的解决方法:通过 id 获取元素并使用 element.setAttribute(attributename, attributevalue)
设置类型
<script>
export let id = "";
export let placeholder = "";
export let label = "";
export let description = "";
export let value = "";
export let type = "text";
</script>
<div class="container">
<label>{label}</label>
<input {type} bind:value {placeholder}
on:focus="{() => {
console.log(type)
let inpt = document.getElementById(id)
inpt.setAttribute("type", type)
console.log(inpt)
}}"/>
<p>{description}</p>
</div>
希望对您有所帮助:-)
<!-- InputField.svelte -->
<script>
export let placeholder = "";
export let label = "";
export let description = "";
export let value = "";
export let type = "text";
const handleInputType = (e) => {
e.target.type = type;
};
</script>
<div class="container">
<label>{label}</label>
<input {value} {placeholder} on:input={handleInputType} />
<p>{description}</p>
</div>
我遇到了这个,为了简化,我所做的就像上面一样,基本上我删除了输入中的 {type}
并且在输入时我只是修改目标类型,因为这是一个组件,所以在你的 parent/route svelte 文件上。
<InputField type="email" bind:value={emailValue} />
类似的东西怎么样?
export let type: 'email' | 'text' | 'password' | 'number' = 'text'
let ref: HTMLInputElement
onMount(() => {
if (ref) {
ref.type = type
}
})
然后
<input bind:this={ref} />
或
export let type: 'email' | 'text' | 'password' | 'number' = 'text'
const ref = (node: HTMLInputElement) => {
node.type = type
}
然后
<input use:ref />
另一种可能的解决方案不是很优雅或 DRY,但不需要自己模拟核心 Svelte 功能是简单地在 type
上分支并相应地呈现不同的输入:
<script>
export let name;
export let value;
export let type = 'text';
</script>
{#if type === 'password'}
<input
type="password"
id={name}
{name}
on:change
on:blur
bind:value
/>
{:else if type === 'email'}
<input
type="email"
id={name}
{name}
on:change
on:blur
bind:value
/>
{:else if type === 'number'}
<input
type="number"
id={name}
{name}
on:change
on:blur
bind:value
/>
{:else if type === 'date'}
<input
type="date"
id={name}
{name}
on:change
on:blur
bind:value
/>
{:else}
<input
type="text"
id={name}
{name}
on:change
on:blur
bind:value
/>
{/if}
use
组件中设置节点类型的函数:
Input.svelte:
<script>
export let type = 'text'
export let label
export let value
function typeAction(node) {
node.type = type;
}
</script>
<div class="space-y-1">
<label>{label}</label>
<input use:typeAction bind:value class="rounded-md w-full">
<p class="text-sm text-red-600">errors</p>
</div>
Form.svelte:
<form on:submit|preventDefault={login}>
<Input type="email" label="Email" bind:value={values.email}/>
<Input type="password" label="Password" bind:value={values.password}/>
<Button type="submit" label="Login"/>
</form>
将输入导出到独立组件,然后手动处理输入而不是绑定,然后可以设置动态类型。
然后你可以将值绑定到组件。
参见此处示例:
https://svelte.dev/repl/77f694a1851d464b85b382f4f152cb8e?version=3.46.4
我试图为我的项目创建一个 Input
组件。我想在 input
元素
但是当我在 input
上动态设置类型属性时,我得到错误提示
'type' attribute cannot be dynamic if input uses two-way binding
所以有什么解决方法可以动态设置类型属性而不会丢失双向绑定
Input.svelte
<script>
export let placeholder = "";
export let label = "";
export let description = "";
export let value = "";
export let type = "text";
</script>
<div class="container">
<label>{label}</label>
<input {type} bind:value {placeholder} />
<p>{description}</p>
</div>
type
双向绑定必须是静态的原因是 Svelte 生成的代码对于不同类型的输入是不同的。例如,number
和 range
输入必须将其值强制转换为数字,一些输入需要 change
事件侦听器而不是 input
事件,反之亦然,等等。
但是您可以手动执行生成的代码会执行的相同操作 — 添加一个反映状态的事件侦听器:
<script>
export let placeholder = "";
export let label = "";
export let description = "";
export let value = "";
export let type = "text";
const handleInput = e => {
// in here, you can switch on type and implement
// whatever behaviour you need
value = type.match(/^(number|range)$/)
? +e.target.value
: e.target.value;
};
</script>
<div class="container">
<label>{label}</label>
<input {type} {value} {placeholder} on:input={handleInput} />
<p>{description}</p>
</div>
一个简单的解决方法:通过 id 获取元素并使用 element.setAttribute(attributename, attributevalue)
设置类型
<script>
export let id = "";
export let placeholder = "";
export let label = "";
export let description = "";
export let value = "";
export let type = "text";
</script>
<div class="container">
<label>{label}</label>
<input {type} bind:value {placeholder}
on:focus="{() => {
console.log(type)
let inpt = document.getElementById(id)
inpt.setAttribute("type", type)
console.log(inpt)
}}"/>
<p>{description}</p>
</div>
希望对您有所帮助:-)
<!-- InputField.svelte -->
<script>
export let placeholder = "";
export let label = "";
export let description = "";
export let value = "";
export let type = "text";
const handleInputType = (e) => {
e.target.type = type;
};
</script>
<div class="container">
<label>{label}</label>
<input {value} {placeholder} on:input={handleInputType} />
<p>{description}</p>
</div>
我遇到了这个,为了简化,我所做的就像上面一样,基本上我删除了输入中的 {type}
并且在输入时我只是修改目标类型,因为这是一个组件,所以在你的 parent/route svelte 文件上。
<InputField type="email" bind:value={emailValue} />
类似的东西怎么样?
export let type: 'email' | 'text' | 'password' | 'number' = 'text'
let ref: HTMLInputElement
onMount(() => {
if (ref) {
ref.type = type
}
})
然后
<input bind:this={ref} />
或
export let type: 'email' | 'text' | 'password' | 'number' = 'text'
const ref = (node: HTMLInputElement) => {
node.type = type
}
然后
<input use:ref />
另一种可能的解决方案不是很优雅或 DRY,但不需要自己模拟核心 Svelte 功能是简单地在 type
上分支并相应地呈现不同的输入:
<script>
export let name;
export let value;
export let type = 'text';
</script>
{#if type === 'password'}
<input
type="password"
id={name}
{name}
on:change
on:blur
bind:value
/>
{:else if type === 'email'}
<input
type="email"
id={name}
{name}
on:change
on:blur
bind:value
/>
{:else if type === 'number'}
<input
type="number"
id={name}
{name}
on:change
on:blur
bind:value
/>
{:else if type === 'date'}
<input
type="date"
id={name}
{name}
on:change
on:blur
bind:value
/>
{:else}
<input
type="text"
id={name}
{name}
on:change
on:blur
bind:value
/>
{/if}
use
组件中设置节点类型的函数:
Input.svelte:
<script>
export let type = 'text'
export let label
export let value
function typeAction(node) {
node.type = type;
}
</script>
<div class="space-y-1">
<label>{label}</label>
<input use:typeAction bind:value class="rounded-md w-full">
<p class="text-sm text-red-600">errors</p>
</div>
Form.svelte:
<form on:submit|preventDefault={login}>
<Input type="email" label="Email" bind:value={values.email}/>
<Input type="password" label="Password" bind:value={values.password}/>
<Button type="submit" label="Login"/>
</form>
将输入导出到独立组件,然后手动处理输入而不是绑定,然后可以设置动态类型。 然后你可以将值绑定到组件。
参见此处示例: https://svelte.dev/repl/77f694a1851d464b85b382f4f152cb8e?version=3.46.4