svelte-materialify icon indicating copy to clipboard operation
svelte-materialify copied to clipboard

<TextField type='number' /> has string value

Open gristow opened this issue 4 years ago • 4 comments

Because the type prop must be static when using two-way value binding (per Rich Harris's answer on StackOverflow), even when we set the type='number' on a <TextField /> the value binding remains to a string.

in PR #193 I proposed a new component <NumberField /> for this, but this posed issues around duplication of styles. I'm opening this issue as a discussion place for a possible implementation.

gristow avatar Apr 18 '21 14:04 gristow

@Florian-Schoenherr @TheComputerM how would you feel about my creating a component <InputField />, which would contain most of what is now in <TextField /> and my previously proposed <NumberField />, as a shared place for those styles. Then <TextField /> and <NumberField /> would both use <InputField /> as a child component?

// InputField.svelte
<script>
   export let type="text";
   ... etc ...
</script>

...etc...
{#if type==='number'}
   <input
    type="number"
    ...etc...
    {...$$restProps} />
{:else}
  <input
    type="text"
    ...etc...
    {...$$restProps} />
{/if}

gristow avatar Apr 18 '21 14:04 gristow

I think there's already an <Input /> component, but it's not documented what it does (it's just a wrapper for some styles and not really an Input). As I don't know what parts of the styling it actually defines, that might be the place to start with this proposal (just finding out what it does or maybe TCM can tell us) and then I'm all for what you proposed :)

One question: 'type' attribute cannot be dynamic if input uses two-way binding is only used because some people only need one kind of input-type, right? Because if it doesn't know the type it would need to add all cases. Let's say there would be a way to tell svelte "I'm using all the input types, just add more coercion logic", then this problem would not exist?

Florian-Schoenherr avatar Apr 18 '21 15:04 Florian-Schoenherr

One question: 'type' attribute cannot be dynamic if input uses two-way binding is only used because some people only need one kind of input-type, right? Because if it doesn't know the type it would need to add all cases.

Yes -- but the only two non-string value types are the type="number" and type="range" input elements. So it's only those two that we'd need to handle. (And, if we handle those, it will match the way Svelte binds numeric inputs.)

You are right that we could handle numeric coercion manually in these cases, though because of the built-in validation that's available on number types, and the different properties they accept, I still think the right move is to have a separate <NumberField /> component. (This may, in part, be because the codebases I work in are strict typescript, and this would allow clearer property definitions on them, and easy typing of values.)

gristow avatar Apr 18 '21 16:04 gristow

I think we should have separate components, yes. Instead of:

{#if type==='number'}
   <input
    type="number"
    ...etc...
    {...$$restProps} />
{:else}
  <input
    type="text"
    ...etc...
    {...$$restProps} />
{/if}

if it's really only those 2 types, we can use Rich's suggestion, maybe even slightly advanced. The reaction to type is not needed if we don't expose <InputField />. There's also a way without regex, valueAsNumber (edit: unless type date is used, which would mean valueAsDate? valueAsNumber? value).

Do people not use valueAsDate for type="date"? I know svelte is just giving back a string on binding. Edit: there was discussion around this here, until then we can provide date as well.

Florian-Schoenherr avatar Apr 19 '21 04:04 Florian-Schoenherr