Is your feature request related to a problem? Please describe.
I am currently making a Input.svelte component to manage common logic:
<script>
export let id;
export let label;
export let type = 'text';
export let value = '';
export let revealed = false;
const revealToggle = (event) => {
const input = event.currentTarget.previousElementSibling;
if (!input) {
return;
}
input.type = input.type === 'password' ? 'text' : 'password';
revealed = !revealed;
}
</script>
<style>
button:focus {
outline: 0 !important;
}
</style>
<label class="block mb-2" for="{id}">{label}</label>
<div class="flex mb-4">
{#if type === 'password'}
<input
{id}
type="password"
placeholder="{label}"
bind:value
class="rounded-r-none border-r-0"
>
<button
title="Afficher le mot de passe"
type="button"
class="border border-gray-400 rounded rounded-l-none px-3 text-gray-500"
on:click={revealToggle}
>
<i class="fa fa-fw {revealed ? 'fa-eye' : 'fa-eye-slash'}"></i>
</button>
{:else}
<input {id} type="text" placeholder="{label}" bind:value>
{/if}
</div>
It is currently not possible to assign a prop to the type html attribute as you well answered here: https://stackoverflow.com/a/57393751/1731473
Otherwise, it will produce this error:
Error: ValidationError: 'type' attribute cannot be dynamic if input uses two-way binding
But it is still possible to do "dynamic" type attribute with a basic if/else logic as you can see in my example.
So I don't understand why things are not simpler. Nowadays, with html5, we have a ton of "text similar input" like date, email, or tel: https://www.w3schools.com/html/html_form_input_types.asp
I would like to avoid to make a if forest if I only need to change the type attribute.
Also, maybe a good place for an another issue, but I can't find an easier way to pass input related directly to the right DOM element in my component without declaring each of them manually (min, max, required etc...), but I don't know if this is doable.
Describe the solution you'd like
Allow to do something like this:
<input {id} {type} placeholder="{label}" bind:value>
With or without two-way binding. The goal is to quickly define what type I want from my input component:
<script>
import Input from './Input.svelte';
</script>
<Input type="text" ... />
Describe alternatives you've considered
The only alternative I found is what you have on my example.
Maybe it's a design issue from my own. In that case, some good advices on this issue and the documentation would be very welcome. :+1:
How important is this feature to you?
It is not very urgent, but I think this is quite useful in order to avoid code repetition on big projects.
@soullivaneuh I've created an example with your component: https://svelte.dev/repl/b220a2c7855a47fcbb713648d33aba49?version=3.14.1
You can use a dynamic type, but you need to handle two-way data binding by yourself via setting a value {value} and listening to changes on:input.
This is exactly what @Rich-Harris proposed in an answer to your question on Stackoverflow.
Moreover, you can write a component which handles all kind of input types: https://svelte.dev/repl/31ee5896ee5c4364bf6d73538c895bd5?version=3.14.1
But, again, handling two-way data binding will be on your side. Different types emit different events, so you will have to subscribe to all required events to properly retrieve the input's value.
The proposal here, I guess, is to allow dynamic type values on inputs with bind:value, and to assume that the type will always be set to a 'normal' text-like one. This is something I've definitely considered before, but I can't find an issue right now where it was discussed. I suppose the question is whether that gotcha (which would need to be documented) is better or worse than having to manually put a on:input event handler on your input. I don't know the answer to that.
Thanks for the samples @rise2semi, I indeed didn't understand that way.
Still, it's kinda workaround to me. It would be great to have this natively managed by Svelte, this is why I opened this issue. :+1:
At least, the current possible implementation is a good candidate for the official documentation/tutorial/examples as this seems to be a quite common case.
I also encountered this problem, so I solved it:
Input component:
<script>
import { onMount } from "svelte";
export let inputType= "text";
export let value = "";
let inputElement;
onMount(() => {
inputElement.type = inputType;
});
</script>
<input
on:keyup
on:change
bind:value
bind:this={inputElement}/>
External call:
<script>
import Input from "./Input.svelte";
let value = "";
let text = "";
function foo(){
if(value.length < 4){
text="Passwod too short";
}else{
text="";
}
}
</script>
<Input bind:value inputType='password' on:change={foo}/>
<p>{text}</p>
I don't know if this is really correct,superficially works.
I would also like to see this, for all of the reasons @soullivaneuh listed.
If the only issue is the difference between number-based inputs (range, number, etc.), text-based (text, email, password, etc.), and [insert type here]-based inputs, the API should make it possible to switch between all input types that all produce the same type for value. My use case is to create a <TextInput/> element that can either be a text, email, or password input.
One option would be to drop the compile-time dynamic-input-type check entirely and let the user run into an error if they end up changing the type to something incompatible. A warning about this could be added to the documentation.
Another option would be to generate slightly less efficient code i.e. change the automatically generated handler any time the type changes.
Another option (which I'm not sure is possible) is to make the type input never reactive, instead using the value provided at initialization.
I want to thank the svelte team for making it so that numbers-typed inputs return numbers.
But in this particular instance, if it's causing an issue like this then I'm 100% for letting developers deal with the conversion of number-based types, which is what they would have to do using vanilla JS anyway, and I'm pretty sure even React just has you (the developer) handle the numbers yourself.
I'm interested in checking out the code responsible, perhaps there's a way for the numbered returns and also a way to dynamically set the type on inputs without needing any of the above work arounds?
@jhechtf the dynamic thing might the perfect solution. If svelte detects that an input's type is two-way bound, it should simply generate an input handler that checks the type each time.
Most helpful comment
I also encountered this problem, so I solved it:
Input component:
External call:
I don't know if this is really correct,superficially works.