Custom form controls

If for some reason you're not using an HTML5 input, select or textarea element as an input, you have three options:

Binding to your stores

You can bind to the data store in order to let Felte manage your custom controls. You'll also need to update your touched store appropriately.

<script>
  import { createForm } from 'felte';

  const { form, data, touched } = createForm({ /* ... */ });

  const initialValue = $data.customControlName;

  $: {
    if (initialValue !== $data.customControlName) {
      $touched.customControlName = true;
    }
  }
</script>

<form use:form>
  <SomeCustomControl bind:value={$data.customControlName} />
</form>

Using helpers

You may also use any of the returned helpers from createForm for this as well.

<script>
  import { createForm } from 'felte';

  const { form, setFields } = createForm({
    initialValues: {
      customControlName: '',
    },
    // ...
  });

  function handleChange(event) {
    setFields('customControlName', event.detail.value, true);
  }
</script>

<form use:form>
  <SomeCustomControl on:customChangeEvent="{handleChange}" />
</form>

If your custom form control uses an input or other native form control behind the scenes, you may dispatch an input or change event from it when the value of it changes (if your control does not do this already). Felte listens to change events for <input type="checkbox">, <input type="radio">, <select> and <input type="file"> elements; and for input events on any other type of input.

Using createField

You might want to create a shareable component that should work with Felte without needing to use any of the helpers. If said component uses a native HTML control, and your user interacts directly with it, then assigning a name to it should be enough for Felte to manage it. But there might be situations on which the control itself is completely custom made, maybe using an input[type="hidden"] behind the scenes or not using a native control at all (e.g. a contenteditable div). For this situations you can use createField.

createField provides you with some helpers to make your custom control visible to Felte without needing to use any of createForm's helpers. Its usage looks something like:

<script>
  import { createField } from 'felte';

  export let name;

  const { field, onInput, onBlur } = createField(name);

  function handleInput(e) {
    onInput(e.currentTarget.innerText);
  }
</script>

<div
  use:field
  on:input={handleInput}
  on:blur={onBlur}
  aria-labelledby={labelId}
  role="textbox"
  contenteditable="true"
  tabindex="0"
  />

The previous component will behave just like a regular input when used within a form managed by Felte. Only requiring a name prop.

createField can be called in two different ways:

The options accepted by createField are:

createField returns an object with the following properties:

NOTE: when creating custom controls like this, be mindful of the accessibility of your component. Handling proper keyboard interactions, roles and labels is a must for your custom control to be seen as an input by assistive technologies.