Skip to content

Overview

The provided code is a Svelte component that creates a form input control for various form fields. It utilizes the svelte library for creating and handling custom events. The component supports attributes like name, label, required, readonly, placeholder, and type to customize the input behavior. The form context is obtained using svelte's getContext function to access form state and methods. The component renders the input element, applying appropriate classes and attributes based on the provided props. It also handles form validation and error display, showing error messages when the input is touched and contains errors. These validations and errors are obtained from the parent Form component.

Implementation

Below is how the TextInput 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 = ""
  export let type = "text"

  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" 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} {...$$restProps}/>
  {:else}
    <input class="rounded-md p-2 border-gray-300 border bg-white {otherClasses}" {name} {required} {readonly} class:bg-gray-100={readonly} {placeholder} on:change={onChange} {type} {...$$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>

Released under the MIT License.