# Controlled fields

By default, all form fields are uncontrolled because that's the default behavior of the browser. For a simple login or contact form this is quite sufficient.

## Why controlled?

As soon as your forms become more complex, for example you set initial values or change the values of a form field via <Link href="/methods/api/setInput/">`setInput`</Link>, it becomes necessary that you control your fields yourself. For example, depending on which HTML form field you use, you may need to set the `value`, `checked` or `selected` attributes.

### Text input example

For a text input field you simply add the `value` attribute and pass the value of the field:

```tsx
<Field
  of={loginForm}
  path={['firstName']}
  render$={(field) => (
    <input {...field.props} type="text" value={field.input.value} />
  )}
/>
```

### Exception for files

The HTML `<input type="file" />` element is an exception because it cannot be controlled. However, you have the possibility to control the UI around it. For inspiration you can use the code of our <a href={`${import.meta.env.PUBLIC_GITHUB_URL}/blob/main/playgrounds/qwik/src/components/FileInput.tsx`} target="\_blank" rel="noreferrer">`FileInput`</a> component from our <Link href="/playground/">playground</Link>.

## Numbers and dates

To make the fields of numbers and dates controlled, further steps are required, because the `<input />` element natively understands only strings as value.

### Number input example

Since not every input into an `<input type="number" />` field is a valid number, for example when typing floating numbers, the value may be `NaN` in between. You have to catch this case, otherwise the whole input will be removed when `NaN` is passed. It is best to encapsulate this logic in a separate component as described in the <Link href="/qwik/guides/input-components/">input components</Link> guide.

```tsx
import type { FieldElementProps } from '@formisch/qwik';
import { component$, useComputed$ } from '@qwik.dev/core';

interface NumberInputProps extends FieldElementProps {
  type: 'number';
  label?: string;
  placeholder?: string;
  input: number | undefined;
  errors: [string, ...string[]] | null;
  required?: boolean;
}

export const NumberInput = component$<NumberInputProps>(
  ({ input, label, errors, name, ...inputProps }) => {
    // Update computed value if not NaN
    const value = useComputed$(() =>
      !Number.isNaN(input) ? input : undefined
    );

    return (
      <div>
        {label && <label for={name}>{label}</label>}
        <input
          {...inputProps}
          id={name}
          name={name}
          type="number"
          value={value.value}
          aria-invalid={!!errors}
          aria-errormessage={`${name}-error`}
        />
        {errors && <div id={`${name}-error`}>{errors[0]}</div>}
      </div>
    );
  }
);
```

### Date input example

A date or a number representing a date must be converted to a string before it can be passed to an `<input type="date" />` field. Since it is a calculated value, you can use `useComputed$` for this.

```tsx
import type { FieldElementProps } from '@formisch/qwik';
import { component$, useComputed$ } from '@qwik.dev/core';

interface DateInputProps extends FieldElementProps {
  type: 'date';
  label?: string;
  placeholder?: string;
  input: Date | number | undefined;
  errors: [string, ...string[]] | null;
  required?: boolean;
}

export const DateInput = component$<DateInputProps>(
  ({ input, label, errors, name, ...inputProps }) => {
    // Transform date or number to string
    const value = useComputed$(() =>
      input &&
      !Number.isNaN(typeof input === 'number' ? input : input.getTime())
        ? new Date(input).toISOString().split('T', 1)[0]
        : ''
    );

    return (
      <div>
        {label && <label for={name}>{name}</label>}
        <input
          {...inputProps}
          id={name}
          name={name}
          type="date"
          value={value.value}
          aria-invalid={!!errors}
          aria-errormessage={`${name}-error`}
        />
        {errors && <div id={`${name}-error`}>{errors[0]}</div>}
      </div>
    );
  }
);
```

## Custom inputs and component libraries

Some component libraries don't expose the underlying native HTML element, which means you cannot spread `field.props` onto them. For these cases, use `field.onInput` to set the value programmatically.

```tsx
import { DatePicker } from 'some-component-library';

<Field
  of={form}
  path={['date']}
  render$={(field) => (
    <DatePicker
      value={field.input.value}
      onChange$={(newDate) => field.onInput(newDate)}
    />
  )}
/>;
```

This is useful for:

- **Component libraries** that wrap native elements without exposing them
- **Complex custom inputs** like date pickers, rich text editors, or color pickers

The `field.onInput` method updates the field value and triggers validation, just like a native input would.

## Next steps

Now that you understand controlled fields, you can explore more advanced topics like <Link href="/qwik/guides/nested-fields/">nested fields</Link> and <Link href="/qwik/guides/field-arrays/">field arrays</Link> to handle complex form structures.
