Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bug]: Combo box is not working. #3707

Open
1 of 2 tasks
akeakun opened this issue May 10, 2024 · 8 comments
Open
1 of 2 tasks

[bug]: Combo box is not working. #3707

akeakun opened this issue May 10, 2024 · 8 comments
Labels
bug Something isn't working

Comments

@akeakun
Copy link

akeakun commented May 10, 2024

Describe the bug

the default code for combobox in a next.js app throws this error:

Unhandled Runtime Error
TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))

Affected component/components

ComboBox

How to reproduce

just copy the default code for combo box from shadcnui.com/combobox and paste it in page.tsx
run the code and the error should pop up while trying to click the PopoverTrigger button.

Codesandbox/StackBlitz link

No response

Logs

No response

System Info

browser

Before submitting

  • I've made research efforts and searched the documentation
  • I've searched for existing issues
@akeakun akeakun added the bug Something isn't working label May 10, 2024
@QAQmmttyyy
Copy link

me too. I use the example code in the popover anchor, maybe we should add the CommandList comp:
image

@QAQmmttyyy
Copy link

maybe the cmdk package has some changes and the shadcnui not response to.

@0-don
Copy link

0-don commented May 11, 2024

you need to use this version, v1 doesnt work

    "cmdk": "^0.2.1",

or

tailwind.config.ts

  plugins: [
    require("tailwindcss-animate"),
    function ({ addUtilities }) {
      addUtilities({
        ".popover-content-width-same-as-its-trigger": {
          width: "var(--radix-popover-trigger-width)",
          "max-height": "var(--radix-popover-content-available-height)",
        },
      });
    },
  ],

my-combobox.tsx

type MyComboboxProps = {
  label?: string;
  value: string;
  setValue: (value: string) => void;
  values: { label: string; value: string }[];
  inputDisabled?: boolean;
  inputPlaceholder?: string;
};

export const MyCombobox: React.FC<MyComboboxProps> = (props) => {
  const [open, setOpen] = useState(false);

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <div className="flex flex-col w-full">
        {props.label && <Label className="mb-1">{props.label}</Label>}
        <PopoverTrigger asChild>
          <Button
            variant="outline"
            role="combobox"
            aria-expanded={open}
            className=" justify-between"
          >
            {props.value
              ? props.values.find((item) => item.value === props.value)?.label
              : props.label + "..."}
            <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
          </Button>
        </PopoverTrigger>
      </div>
      <PopoverContent
        className={"popover-content-width-same-as-its-trigger p-0"}
      >
        <Command>
          {props.inputDisabled && (
            <CommandInput placeholder={props.inputPlaceholder} />
          )}
          <CommandEmpty>NOTHING_FOUND</CommandEmpty>
          <CommandGroup>
            <CommandList>
              {props.values.map((item) => (
                <CommandItem
                  key={item.value}
                  value={item.value}
                  onSelect={(currentValue) => {
                    props.setValue(
                      currentValue === props.value ? "" : currentValue
                    );
                    setOpen(false);
                  }}
                >
                  <Check
                    className={cn(
                      "mr-2 h-4 w-4",
                      props.value === item.value ? "opacity-100" : "opacity-0"
                    )}
                  />
                  {item.label}
                </CommandItem>
              ))}
            </CommandList>
          </CommandGroup>
        </Command>
      </PopoverContent>
    </Popover>
  );
};

@Woofer21
Copy link

you need to use this version, v1 doesnt work

    "cmdk": "^0.2.1",

Great catch, once downgrading I no longer run into the issue.

@HiggsWRX
Copy link

HiggsWRX commented May 12, 2024

Just wrap CommandGroup in a CommandList and it will work on latest cmdk. Move the CommandEmpty inside as well.

It should look like this: (just command, popover stuff removed for brevity)

      <Command>
        <CommandInput placeholder="Search ..." />
        <CommandList>
          <CommandEmpty>No option found.</CommandEmpty>
          <CommandGroup>
            {options.map((option) => {
              return (
                <CommandItem
                  key={option.value}
                  value={option.value}
                  onSelect={(currentValue) => {
                    setValue(currentValue === value ? "" : currentValue);
                    setOpen(false);
                    onValueChange(currentValue);
                  }}
                >
                  <CheckIcon
                    className={cn(
                      "mr-2 h-4 w-4",
                      value === option.value ? "opacity-100" : "opacity-0",
                    )}
                  />
                  {option.label}
                </CommandItem>
              );
            })}
          </CommandGroup>
        </CommandList>
      </Command>

@johncarmack1984
Copy link

you need to use this version, v1 doesnt work

    "cmdk": "^0.2.1",

Weekend saved, nice catch

@DamifeZion
Copy link

Yo bro, the command box may not be working for 2 reasons.

  1. You didnt wrap the CommantGroup or CommandItem with the CommandList, its required with the current relaease as of this date.
  2. The exact issue i had struggled with for over 6hours. Go to your Command component, and paste the code below to overwrite the default. Or simply replace every className with data-[disabled] to data-[disabled=true].

"use client";

import * as React from "react";
import { type DialogProps } from "@radix-ui/react-dialog";
import { MagnifyingGlassIcon } from "@radix-ui/react-icons";
import { Command as CommandPrimitive } from "cmdk";

import { cn } from "@/lib/utils";
import { Dialog, DialogContent } from "@/components/ui/dialog";

const Command = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef

(({ className, ...props }, ref) => (
<CommandPrimitive
ref={ref}
className={cn(
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
className
)}
{...props}
/>
));
Command.displayName = CommandPrimitive.displayName;

interface CommandDialogProps extends DialogProps {}

const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
return (
<Dialog {...props}>


{children}



);
};

const CommandInput = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef

(({ className, ...props }, ref) => (

));

CommandInput.displayName = CommandPrimitive.Input.displayName;

const CommandList = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef

(({ className, ...props }, ref) => (
<CommandPrimitive.List
ref={ref}
className={cn(
"max-h-[300px] overflow-y-auto overflow-x-hidden",
className
)}
{...props}
/>
));

CommandList.displayName = CommandPrimitive.List.displayName;

const CommandEmpty = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef

((props, ref) => (
<CommandPrimitive.Empty
ref={ref}
className="py-6 text-center text-sm"
{...props}
/>
));

CommandEmpty.displayName = CommandPrimitive.Empty.displayName;

const CommandGroup = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef

(({ className, ...props }, ref) => (
<CommandPrimitive.Group
ref={ref}
className={cn(
"overflow-hidden p-1 text-foreground [&[cmdk-group-heading]]:px-2 [&[cmdk-group-heading]]:py-1.5 [&[cmdk-group-heading]]:text-xs [&[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
className
)}
{...props}
/>
));

CommandGroup.displayName = CommandPrimitive.Group.displayName;

const CommandSeparator = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef

(({ className, ...props }, ref) => (
<CommandPrimitive.Separator
ref={ref}
className={cn("-mx-1 h-px bg-border", className)}
{...props}
/>
));
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;

const CommandItem = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef

(({ className, ...props }, ref) => (
<CommandPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50",
className
)}
{...props}
/>
));

CommandItem.displayName = CommandPrimitive.Item.displayName;

const CommandShortcut = ({
className,
...props
}: React.HTMLAttributes) => {
return (
<span
className={cn(
"ml-auto text-xs tracking-widest text-muted-foreground",
className
)}
{...props}
/>
);
};
CommandShortcut.displayName = "CommandShortcut";

export {
Command,
CommandDialog,
CommandInput,
CommandList,
CommandEmpty,
CommandGroup,
CommandItem,
CommandShortcut,
CommandSeparator,
};

@Olalexy1
Copy link

Just wrap CommandGroup in a CommandList and it will work on latest cmdk. Move the CommandEmpty inside as well.

It should look like this: (just command, popover stuff removed for brevity)

      <Command>
        <CommandInput placeholder="Search ..." />
        <CommandList>
          <CommandEmpty>No option found.</CommandEmpty>
          <CommandGroup>
            {options.map((option) => {
              return (
                <CommandItem
                  key={option.value}
                  value={option.value}
                  onSelect={(currentValue) => {
                    setValue(currentValue === value ? "" : currentValue);
                    setOpen(false);
                    onValueChange(currentValue);
                  }}
                >
                  <CheckIcon
                    className={cn(
                      "mr-2 h-4 w-4",
                      value === option.value ? "opacity-100" : "opacity-0",
                    )}
                  />
                  {option.label}
                </CommandItem>
              );
            })}
          </CommandGroup>
        </CommandList>
      </Command>

Thanks man.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

8 participants