# Autocomplete

Autocomplete unterstützt bei der Texteingabe durch kontextbezogene Vorschläge. Die Auswahl ist optional, eigene Eingaben bleiben möglich. Typischerweise wird die Komponente mit TextField oder SearchField kombiniert.

## Overview

# Playground

Lege `<Autocomplete />`, um ein
[TextField](/04-components/form-controls/text-field/overview) oder ein
[SearchField](/04-components/form-controls/search-field/overview), um
Texteigaben mit Vorschlägen zu unterstützen.

```tsx
import {
  Option,
  Label,
  TextField,
  Autocomplete,
} from "@mittwald/flow-react-components";
import { useState } from "react";

export default () => {
  const [input, setInput] = useState("");

  const generateSuggestItems = () => {
    return [
      "example.com",
      "test.org",
      "email.net",
      "mail.com",
    ]
      .map((d) => {
        const email = `${input.split("@")[0]}@${d}`;
        return (
          <Option
            key={email}
            value={email}
            textValue={email}
          >
            {email}
          </Option>
        );
      })
      .filter(() => input);
  };

  return (
    <Autocomplete>
      <TextField value={input} onChange={setInput}>
        <Label>Email</Label>
      </TextField>
      {generateSuggestItems()}
    </Autocomplete>
  );
}
```

---

# Benutzerdefinierte Filter

Schränke die Optionen, die dem User zur Auswahl stehen mithilfe von Filtern ein.

```tsx
import {
  Option,
  Label,
  TextField,
  Autocomplete,
} from "@mittwald/flow-react-components";
import { useState } from "react";

export default () => {
  const [input, setInput] = useState("");

  const generateSuggestItems = () => {
    return [
      "example.com",
      "test.org",
      "email.net",
      "mail.com",
    ]
      .map((d) => {
        const email = `${input.split("@")[0]}@${d}`;
        return (
          <Option
            key={email}
            value={email}
            textValue={email}
          >
            {email}
          </Option>
        );
      })
      .filter(() => input);
  };

  const domainDotComFilter = (
    textValue: string,
    ignored_inputValue: string,
  ) => {
    return textValue.includes(".com");
  };

  return (
    <Autocomplete filter={domainDotComFilter}>
      <TextField value={input} onChange={setInput}>
        <Label>Email</Label>
      </TextField>
      {generateSuggestItems()}
    </Autocomplete>
  );
}
```

---

# Kombiniere mit ...

## SearchField

Nutze `<Autocomplete />` mit einem
[SearchField](/04-components/form-controls/search-field/overview), um die User
beim Suchen mit Vorschlägen zu unterstützen.

```tsx
import {
  Label,
  Autocomplete,
  SearchField,
  Option,
} from "@mittwald/flow-react-components";
import { useState } from "react";

export default () => {
  const [input, setInput] = useState("");

  const generateSuggestItems = () => {
    return [
      "example.com",
      "test.org",
      "email.net",
      "mail.com",
    ]
      .map((d) => {
        const email = `${input.split("@")[0]}@${d}`;
        return (
          <Option
            key={email}
            value={email}
            textValue={email}
          >
            {email}
          </Option>
        );
      })
      .filter(() => input);
  };

  return (
    <Autocomplete>
      <SearchField value={input} onChange={setInput}>
        <Label>Email</Label>
      </SearchField>
      {generateSuggestItems()}
    </Autocomplete>
  );
}
```

## React Hook Form

Weitere Details zur Formularlogik und -validierung sind in der Component
[Form (React Hook Form)](/04-components/react-hook-form/form/overview) zu
finden.

```tsx
import {
  Label,
  Autocomplete,
  Section,
  TextField,
  Option,
} from "@mittwald/flow-react-components";
import { useForm, useWatch } from "react-hook-form";
import {
  Form,
  SubmitButton,
  typedField,
} from "@mittwald/flow-react-components/react-hook-form";
import { sleep } from "@/content/04-components/actions/action/examples/lib";

export default () => {
  const form = useForm<{ email: string }>({
    defaultValues: {
      email: "",
    },
  });
  const Field = typedField(form);

  const currentEmailValue = useWatch({
    name: "email",
    control: form.control,
  });

  const generateSuggestItems = () => {
    return [
      "example.com",
      "test.org",
      "email.net",
      "mail.com",
    ]
      .map((d) => {
        const email = `${currentEmailValue.split("@")[0]}@${d}`;
        return (
          <Option
            key={email}
            value={email}
            textValue={email}
          >
            {email}
          </Option>
        );
      })
      .filter(() => currentEmailValue);
  };

  return (
    <Section>
      <Form form={form} onSubmit={sleep}>
        <Field
          name="email"
          rules={{
            required: "Bitte wähle eine App aus",
          }}
        >
          <Autocomplete>
            <TextField>
              <Label>Test</Label>
            </TextField>
            {generateSuggestItems()}
          </Autocomplete>
        </Field>
        <SubmitButton>Speichern</SubmitButton>
      </Form>
    </Section>
  );
}
```


## Develop

# Properties

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `children` | `ReactNode` | - | - |
| `className` | `string` | - | The elements class name. |
| `wrapWith` | `ReactElement<unknown, string \| JSXElementConstructor<any>>` | - | - |
| `ref` | `Ref<HTMLSpanElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see [React Docs](https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom) |
| `key` | `Key` | - | - |
| `slot` | `string` | - | A slot name for the component. Slots allow the component to receive props from a parent component. An explicit `null` value indicates that the local props completely override all props received from a parent. |
| `filter` | `((textValue: string, inputValue: string, node: Node<object>) => boolean)` | - | An optional filter function used to determine if a option should be included in the autocomplete list. Include this if the items you are providing to your wrapped collection aren't filtered by default. |
| `disableAutoFocusFirst` | `boolean` | `false` | Whether or not to focus the first item in the collection after a filter is performed. Note this is only applicable if virtual focus behavior is not turned off via `disableVirtualFocus`. |
| `disableVirtualFocus` | `boolean` | `false` | Whether the autocomplete should disable virtual focus, instead making the wrapped collection directly tabbable. |


## Guidelines

# Grundlagen

Autocomplete dient dazu, Usern beim Ausfüllen von Texteingabefeldern durch
Vorschläge zu unterstützen. Während der Eingabe werden relevante Optionen
angezeigt, aus denen ausgewählt werden kann. Die Auswahl eines Vorschlags ist
optional, User können auch eigene Eingaben vornehmen. Autocomplete wird
typischerweise in Kombination mit Komponenten wie
[TextField](/04-components/form-controls/text-field/overview) oder
[SearchField](/04-components/form-controls/search-field/overview) eingesetzt.

## Best practices

Achte bei der Verwendung von Autocomplete darauf, dass ...

- die Vorschläge kontextbezogen sind.
- die Vorschlagsliste bei Bedarf sinnvoll vorgefiltert werden kann (z. B. anhand
  von Kategorien oder Kontext).
- bei leerem Eingabefeld zunächst keine Vorschläge angezeigt werden.

## Verwendung

Verwende ein Autocomplete, um ...

- die Effizienz bei der Dateneingabe zu verbessern, insbesondere bei bekannten
  oder häufig genutzten Optionen.
- Tippfehler zu vermeiden und die Datenqualität zu erhöhen.
- lange Auswahlmenüs zu vermeiden, indem Vorschläge dynamisch gefiltert werden.

## Autocomplete vs. ComboBox

Autocomplete und [ComboBoxen](/04-components/form-controls/combo-box/overview)
sehen oft ähnlich aus, erfüllen aber unterschiedliche Zwecke.

- Usern zu ermöglichen, freie Eingaben zu machen, während Vorschläge zur Auswahl angezeigt werden. 
- bei langen oder dynamischen Datenlisten (z. B. Städte, Usernamen, Tags).

- aus einer vordefinierten Liste von Optionen eine Auswahl zu treffen.
- bei bekannten, überschaubaren Optionen (z. B. Sprachen, Kategorien, Geschlecht).

