Input components
To make your code more readable, we recommend that you develop your own input components if you are not using a prebuilt UI library. There you can encapsulate logic to display error messages, for example.
If you're already a bit more experienced, you can use the input components we developed for our playground as a starting point. You can find the code in our GitHub repository here.
Why input components?
Currently, your fields might look something like this:
<Field
of={loginForm}
path={['email']}
render$={(field) => (
<div>
<label for={field.props.name}>Email</label>
<input
{...field.props}
id={field.props.name}
value={field.input.value}
type="email"
required
/>
{field.errors.value && <div>{field.errors.value[0]}</div>}
</div>
)}
/>If CSS and a few more functionalities are added here, the code quickly becomes confusing. In addition, you have to rewrite the same code for almost every form field.
Our goal is to develop a TextInput component so that the code ends up looking like this:
<Field
of={loginForm}
path={['email']}
render$={(field) => (
<TextInput
{...field.props}
type="email"
label="Email"
input={field.input.value}
errors={field.errors.value}
required
/>
)}
/>Create an input component
In the first step, you create a new file for the TextInput component and, if you use TypeScript, define its properties.
import type { FieldElementProps } from '@formisch/qwik';
import { component$, type ReadonlySignal } from '@qwik.dev/core';
interface TextInputProps extends FieldElementProps {
type: 'text' | 'email' | 'tel' | 'password' | 'url' | 'date';
label?: string;
placeholder?: string;
input: ReadonlySignal<string | undefined>;
errors: ReadonlySignal<[string, ...string[]] | null>;
required?: boolean;
}Component function
In the next step, add the component function to the file. We can destructure the props directly.
import type { FieldElementProps } from '@formisch/qwik';
import { component$, type ReadonlySignal } from '@qwik.dev/core';
interface TextInputProps extends FieldElementProps {
/* ... */
}
export const TextInput = component$<TextInputProps>(
({ input, label, errors, ...props }) => {
// Component JSX will go here
}JSX code
After that, you can add the JSX code to the return statement.
import type { FieldElementProps } from '@formisch/qwik';
import { component$, type ReadonlySignal } from '@qwik.dev/core';
interface TextInputProps extends FieldElementProps {
/* ... */
}
export const TextInput = component$<TextInputProps>(
({ input, label, errors, ...props }) => {
const { name, required } = props;
return (
<div>
{label && (
<label for={name}>
{label} {required && <span>*</span>}
</label>
)}
<input
{...props}
id={name}