Field

Die Field-Component integriert die Form Controls von Flow nahtlos in das Formular-Management von React Hook Form.GitHub

Die Field-Component nutzt dieselben Properties wie die Controller-Component von React Hook Form – mit Ausnahme von render.

Playground

import { useForm } from "react-hook-form";
import {
  Field,
  Form,
} from "@mittwald/flow-react-components/react-hook-form";
import {
  Label,
  TextField,
} from "@mittwald/flow-react-components";

export default () => {
  interface Values {
    name: string;
  }
  const form = useForm<Values>();

  return (
    <Form form={form} onSubmit={console.log}>
      <Field
        name="name"
        rules={{
          required: "Bitte gib einen Namen ein",
        }}
      >
        <TextField>
          <Label>Name</Label>
        </TextField>
      </Field>
    </Form>
  );
}

typedField

Die typedField(form)-Factory erzeugt eine Field-Component, die an den Typ des jeweiligen Forms angepasst ist. Dadurch führen beispielsweise unbekannte Field-Namen zu einem TypeScript-Fehler.

import { useForm } from "react-hook-form";
import {
  Form,
  typedField,
} from "@mittwald/flow-react-components/react-hook-form";
import {
  Label,
  TextField,
} from "@mittwald/flow-react-components";

export default () => {
  interface Values {
    myField: string;
  }
  const form = useForm<Values>();

  // Only `myField` is allowed for name prop
  const Field = typedField(form);

  return (
    <Form form={form} onSubmit={console.log}>
      <Field name="myField">
        <TextField>
          <Label>Name</Label>
        </TextField>
      </Field>
    </Form>
  );
}

custom field components

asd

import {
  type FieldPropsComponent,
  Form,
  SubmitButton,
  typedField,
  useFieldProps,
} from "@mittwald/flow-react-components/react-hook-form";
import {
  ActionGroup,
  Label,
  Section,
} from "@mittwald/flow-react-components";
import { type FC, useMemo } from "react";
import { useForm } from "react-hook-form";

export default () => {
  const CustomFieldComponent: FC<FieldPropsComponent> = (
    props,
  ) => {
    const {
      ref,
      children,
      value,
      defaultValue,
      onChange,
      onBlur,
      form,
      name,
      disabled,
      isReadOnly,
      fieldComponents: {
        FieldErrorView,
        FieldComponentContainer,
        FieldChildrenContainer,
      },
    } = useFieldProps(props);

    return (
      <FieldComponentContainer>
        <FieldChildrenContainer>
          {children}
        </FieldChildrenContainer>
        <input
          readOnly={isReadOnly}
          disabled={disabled}
          form={form}
          name={name}
          ref={ref}
          style={{ order: 2 }}
          value={value}
          defaultValue={defaultValue}
          onChange={onChange}
          onBlur={onBlur}
        />
        <FieldErrorView />
      </FieldComponentContainer>
    );
  };

  // only necessary because CustomFieldComponent is an inline component in this demo page
  const MemoCustomFieldComponent = useMemo(
    () => CustomFieldComponent,
    [],
  );

  interface Values {
    myCustomField: string;
  }
  const form = useForm<Values>();
  const Field = typedField(form);

  return (
    <Form form={form} onSubmit={console.log}>
      <Section>
        <Field
          name="myCustomField"
          rules={{
            required: "Bitte gib eine Nachricht ein",
          }}
        >
          <MemoCustomFieldComponent>
            <Label>Name</Label>
          </MemoCustomFieldComponent>
        </Field>
        <ActionGroup>
          <SubmitButton>Speichern</SubmitButton>
        </ActionGroup>
      </Section>
    </Form>
  );
}

Overview