Appearance
Overview
The NumberInput component shares a similar implementation to the TextInput component but is specifically designed to handle numeric input. Like the TextInput, it allows customization of attributes such as name, label, required, readonly, placeholder, and type. However, the NumberInput is tailored to handle numeric values, making it ideal for form fields that require only numerical input. The components streamline input handling, validation, and error display, providing a user-friendly and reusable solution for numeric form inputs in the application.
Implementation
Below is how the NumberInput component was created.
svelte
<script>
import { getContext, createEventDispatcher } from "svelte"
import { fade } from "svelte/transition"
import { key } from "./form"
import { uniqueId } from "lodash"
export let name
export let label = name
export let required = false
export let readonly = false
export let placeholder = ""
export let showRequiredIndicator = true
export let otherClasses = ""
let id = uniqueId(name)
let dispatch = createEventDispatcher()
const { touched, errors, data, setData } = getContext(key)
function onChange() {
dispatch("change", { name, value: $data[name]})
}
$: hasError = $touched[name] && $errors[name]?.length
$: error = $errors[name]?.join(", ")
</script>
<div class="form-control">
<label class="label flex text-truncate text-ellipsis" for={id}>
<span class="label-text">
{label}
{#if required && showRequiredIndicator}
<span class="text-red-600" in:fade out:fade>*</span>
{/if}
</span>
</label>
{#if readonly}
<input class="rounded-md p-2 border-gray-300 border bg-white {otherClasses}" value={$data[name]} {required} {readonly} class:bg-gray-100={readonly} {placeholder} on:change={onChange} type="number" {...$$restProps}/>
{:else}
<input class="rounded-md p-2 border-gray-300 border bg-white {otherClasses}" value={$data[name]} {name} {required} {readonly} class:bg-gray-100={readonly} {placeholder} on:change={onChange} type="number" {...$$restProps}/>
{/if}
{#if hasError}
<label class="label" for={id} in:fade out:fade>
<span class="label-text-alt text-red-900">{error}</span>
</label>
{/if}
</div>