An autocomplete select input using shadcn/ui+react-hook-form+zod.
Tags: form, tailwindcss, react
Published: 2024-03-16 12:04:05

# Overview

simple answer: 
https://www.armand-salle.fr/post/autocomplete-select-shadcn-ui

# Additional Implementations

Hi,I am currently developing a site called placeof.app and needed to add few things to above implementation like "Changes to the suggest logic""Validating the value with the key’s attribute""i18n". Here is how I did it. I hope it helps.

## Changes to the suggest logic
The [Combobox](https://ui.shadcn.com/docs/components/combobox) of shadcn/ui used in the above implementation is a wrapped version of [cmdk](https://github.com/pacocoursey/cmdk/)’s Combobox. I wanted to change the logic of suggest, so I added my own implementation to the filter as described in cmdk’s documentation. It seems that sorting is also possible. 
For example,change https://github.com/armandsalle/my-site/blob/main/src/components/autocomplete.tsx#L88 to the following:
```
<CommandPrimitive
  filter={(value, search) => {
    if (value.includes(search)) return 1
    return 0
  }}
...
/>
```

## Validating the value with the key’s attribute
### Add key
There are two forms, key and value, and this is the implementation when you need to validate the value with the value of the key. When the key to suggest is confirmed by `handleKeyDown` or other, it calls the parent component’s function with `onValueChange`, and at that time,

```
 onValueChange={(key: SuggestKey) => {
    form.setValue("suggestKeyId", key.suggestKeyId)
    form.setValue("suggestValueType", key.valueType)
}}
```

Use the `setValue` function of react-hook-form to add the confirmed key to the form. At this time, the react-hook-form is defined like this:

```
  type Inputs = z.infer<typeof SuggestKeyFormSchema>
  const form = useForm<Inputs>({
    resolver: zodResolver(SuggestKeyFormSchema),
    defaultValues: defaultValues,
  })
```

### Processing when adding a value
Register the value as follows:
```
    <FormItem>
      <FormControl>
        {specKey?.valueType === SpecValueType.TEXTAREA ? ((
          <Input
            aria-invalid={!!form.formState.errors.value}
            {...form.register("value")}
          />
        )}
      </FormControl>
    </FormItem>
```

And validate using zod’s superRefine as follows. The valueType added when the key is added is used at this time.

```
export const SuggestKeyFormSchema = z
  .object({
    suggestKeyId: z.string().min(1),
    valueType: SuggestValueTypeSchema,
    value: z.string().min(1),
  })
  .superRefine((values, ctx) => {
    if (
      values.valueType === SuggestValueTypeSchema.STRING &&
      values.value.length >= 20
    ) {
      ctx.addIssue({
        message: "need to be less than 20 words",
        code: z.ZodIssueCode.custom,
        path: ["value"],
      })
    }

   ....
  })
```

## i18n
By the way, the key is displayed by referring to the i18n file.

Conversion location for the suggest list https://github.com/armandsalle/my-site/blob/main/src/components/autocomplete.tsx#L36

Conversion location for the confirmed key https://github.com/armandsalle/my-site/blob/main/src/components/autocomplete.tsx#L128

# Conclusion
My special thanks to Armand.