shadcn-ui / ui

Beautifully designed components that you can copy and paste into your apps. Accessible. Customizable. Open Source.
https://ui.shadcn.com
MIT License
73.68k stars 4.53k forks source link

Command Component doesn't properly search #1786

Closed maatouk-j1 closed 1 year ago

maatouk-j1 commented 1 year ago

Hi,

I'm creating a Combobox where users can search and select a cryptocurrency. A parent cryptocurrency has a ticker (some sort of code for the currency), and child cryptocurrencies containing a name and a code.

For example, the USDT cryptocurrency (parent) has the following properties: ticker: USDT child cryptos: 1) - name: Tether (TRON)

Now I want the Command component to have the value of the parent cryptocurrency ticker, but the search functionality should take into consideration the child cryptocurrencies names and codes, not just the parent cryptocurrency ticker.

Code:

 <Form {...form}>
    <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
      <FormField
        control={form.control}
        name="cryptocurrencyTicker"
        render={({ field }) => (
          <FormItem className="flex flex-col flex-1 mt-4">
            <FormLabel className="mb-0.5">Cryptocurrency</FormLabel>
            <Popover
              open={showCryptocurrencies}
              onOpenChange={setShowCryptocurrencies}
            >
              <PopoverTrigger asChild>
                <FormControl>
                  <Button
                    variant="outline"
                    role="combobox"
                    aria-expanded={showCryptocurrencies}
                    aria-label="Select a cryptocurrency"
                    className={cn(
                      "justify-between font-normal",
                      !field.value && "text-muted-foreground"
                    )}
                    disabled={isSubmitting}
                  >
                    {field.value
                      ? cryptocurrencies.find(
                          (cryptocurrency: Cryptocurrency) =>
                            cryptocurrency.ticker ===
                            field.value.toUpperCase()
                        )?.currencies[0].name +
                        " (" +
                        field.value.toUpperCase() +
                        ")"
                      : "Select a cryptocurrency"}
                    <CaretSortIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
                  </Button>
                </FormControl>
              </PopoverTrigger>
              <PopoverContent className="max-h-[275px] w-[325px] p-0">
                <Command>
                  <CommandInput placeholder="Search..." />
                  <ScrollArea className="max-h-[225px]">
                    <CommandEmpty>
                      No cryptocurrency found.
                    </CommandEmpty>
                    <CommandGroup>
                      {cryptocurrencies.map(
                        (cryptocurrency: Cryptocurrency) => (
                          <CommandItem
                            value={cryptocurrency.ticker}
                            key={cryptocurrency.ticker}
                            onSelect={() =>
                              handleSelectCryptocurrency({
                                cryptocurrency,
                              })
                            }
                          >
                            <div className="flex items-center md:grow">
                              <div className="flex flex-col mr-auto">
                                <span className="w-full">
                                  {cryptocurrency.currencies[0].name}
                                </span>
                                <span className="w-full text-muted-foreground">
                                  {cryptocurrency.ticker}
                                </span>
                              </div>
                              <div className="flex items-center">
                                <Image
                                  src={
                                    cryptocurrency.currencies[0].logoUrl
                                  }
                                  alt={
                                    cryptocurrency.currencies[0].code
                                  }
                                  width={28}
                                  height={28}
                                  style={{
                                    width: 28,
                                    height: 28,
                                  }}
                                />
                                <CheckIcon
                                  className={cn(
                                    "ml-2 h-5 w-5",
                                    cryptocurrency.currencies[0]
                                      .code === ""
                                      ? "opacity-0"
                                      : cryptocurrency.currencies[0]
                                          .code === field.value
                                      ? "opacity-100"
                                      : "opacity-0"
                                  )}
                                />
                              </div>
                            </div>
                          </CommandItem>
                        )
                      )}
                    </CommandGroup>
                  </ScrollArea>
                </Command>
              </PopoverContent>
            </Popover>
            <FormMessage />
          </FormItem>
        )}
      />

When searching for a cryptocurrency, if I input "USDTTRC20" in the search input field, I get "No cryptocurrency found." instead of getting the correspondent cryptocurrency ticker which is USDT.

It seems that the Command component only searches for whatever value is used in the Command Item component, which in my case is the cryptocurrency ticker.

Is there a way to search for more than a value when using the Command component?

Thanks!

shadcn commented 1 year ago

@maatouk-j1 Have you tried using a custom filter callback for more control?

<Command
  filter={(value, search) => {
    if (value.includes(search)) return 1
    return 0
  }}
/>
maatouk-j1 commented 1 year ago

Thank you for pointing that out! I was able to successfully implement my desired search functionality using the filter.

longopy commented 3 months ago

@maatouk-j1 Have you tried using a custom filter callback for more control?

<Command
  filter={(value, search) => {
    if (value.includes(search)) return 1
    return 0
  }}
/>

The solution fixed the problem. Thank you very much!