ui icon indicating copy to clipboard operation
ui copied to clipboard

Unable to use Dialog inside a DropdownMenu ( with DialogTrigger or without it )

Open voorjordanp opened this issue 1 year ago • 1 comments

I'm having an issue with triggering a dropdown menu correctly. The dropdown menu contains a dialog, and I'm trying to trigger the dropdown using a DropdownMenuTrigger or a DialogTrigger, but neither is working as expected.

Minimal Reproducible Example:


<DropdownMenu>
                                            <DropdownMenuTrigger asChild>
                                                <Button className="bg-gray-800 text-white mb-4 h-12 w-full text-md pr-4 text-left">
                                                    Create Campaign
                                                </Button>
                                            </DropdownMenuTrigger>
                                            <DropdownMenuContent align="center" className="w-[260px] bg-white p-4">
                                                <Dialog>
                                                    <DialogTrigger asChild>
                                                        <DropdownMenuItem className="text-md pt-2">
                                                            trigger dialog from DropdownMenuItem
                                                        </DropdownMenuItem>
                                                    </DialogTrigger>
                                                    <DialogContent className="text-black max-w-[60%] bg-white p-6 h-[600px]">
                                                        <div className="flex gap-10 items-start">
                                                            x
                                                        </div>
                                                    </DialogContent>
                                                </Dialog>

                                                <DropdownMenuSeparator className={"bg-gray-300"}/>

                                                <DropdownMenuItem className="text-md pt-3">
                                                    option 2
                                                </DropdownMenuItem>
                                            </DropdownMenuContent>
                                        </DropdownMenu>

voorjordanp avatar Jan 19 '24 15:01 voorjordanp

`<DropdownMenu modal={false}> <DropdownMenuTrigger className="hover:bg-violet-200 h-8 w-8 flex justify-center items-center rounded-full"> <IoEllipsisVerticalOutline /> </DropdownMenuTrigger> <DropdownMenuContent className="shadow-md bg-white rounded-sm border p-2"> <AlertDialog> <AlertDialogTrigger asChild> <DropdownMenuItem onSelect={(e) => e.preventDefault()} className="flex items-center py-1 px-2 rounded-sm hover:!bg-violet-200 cursor-pointer"> <MdDriveFileRenameOutline className="mr-3" /> Rename </DropdownMenuItem> </AlertDialogTrigger> <AlertDialogContent> <AlertDialogHeader> <AlertDialogTitle>Rename</AlertDialogTitle> <AlertDialogDescription> Please enter a new name for the item: <input type="text" value={docName} onChange={(e) => { setDocName(e.target.value); }} className="py-1 px-2 w-full border-2 outline-violet-800 my-2" /> </AlertDialogDescription> </AlertDialogHeader> <AlertDialogFooter> <AlertDialogCancel onClick={() => { setDocName(Name); }} className="hover:text-gray-800 hover:border-violet-500 text-violet-800"> Cancel </AlertDialogCancel> <AlertDialogAction className={ docName == "" ? "bg-gray-200 text-gray-700 hover:bg-gray-200 hover:text-gray-700 cursor-not-allowed " : "" }> Save </AlertDialogAction> </AlertDialogFooter> </AlertDialogContent> </AlertDialog>

          <AlertDialog>
            <AlertDialogTrigger asChild>
              <DropdownMenuItem
                onSelect={(e) => e.preventDefault()}
                className="flex items-center py-1 px-2 rounded-sm hover:!bg-violet-200 cursor-pointer">
                <MdDeleteForever className="mr-3" />
                Delete
              </DropdownMenuItem>
            </AlertDialogTrigger>
            <AlertDialogContent >
              <AlertDialogHeader>
                <AlertDialogTitle>Delete</AlertDialogTitle>
                <AlertDialogDescription>
                  Are you to delete it permanently ?
                </AlertDialogDescription>
              </AlertDialogHeader>
              <AlertDialogFooter>
                <AlertDialogCancel className="hover:text-gray-800 hover:border-violet-500 text-violet-800">
                  Cancel
                </AlertDialogCancel>
                <AlertDialogAction>Delete</AlertDialogAction>
              </AlertDialogFooter>
            </AlertDialogContent>
          </AlertDialog>
        </DropdownMenuContent>
      </DropdownMenu>`

artistoflight avatar Jan 20 '24 15:01 artistoflight

This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.

shadcn avatar Feb 11 '24 23:02 shadcn

I've come up with the following:

<DropdownMenu open={open} onOpenChange={setOpen}> <Dialog> <DropdownMenuTrigger> <Icons.more /> </DropdownMenuTrigger> <DropdownMenuContent align="start"> <DialogTrigger asChild> <DropdownMenuItem> trigger dialog from DropdownMenuItem </DropdownMenuItem> </DialogTrigger> </DropdownMenuContent> <DialogContent> <div> x </div> </DialogContent> </Dialog> </DropdownMenu>

nuclei272 avatar May 14 '24 00:05 nuclei272

If you want to have a DialogBox pop up from a dropdown menu (for example, a dropdown menu to edit a user, which would pop up a DialogBox modal to edit it), you'll have to do it like this:

<DialogTrigger asChild>
      <DropdownMenuItem onSelect={(e) => e.preventDefault()}>Edit</DropdownMenuItem>
</DialogTrigger>

the key is the preventDefault() call.

shiftcontrol-dan avatar May 31 '24 02:05 shiftcontrol-dan

If you want to have a DialogBox pop up from a dropdown menu (for example, a dropdown menu to edit a user, which would pop up a DialogBox modal to edit it), you'll have to do it like this:

<DialogTrigger asChild>
      <DropdownMenuItem onSelect={(e) => e.preventDefault()}>Edit</DropdownMenuItem>
</DialogTrigger>

the key is the preventDefault() call.

I was using open states all over the place and it was buggy to maintain the open state. this prevent default fixed it for me, because when you select a dropdown item the dropdown menu will close and will close with it the dialog by default

Char99s avatar Jun 11 '24 07:06 Char99s

@Char99s, @shiftcontrol-dan, Using "preventDefault" works by keeping the dialog open. But it remains open even when the dialog is closed. Is there way to automatically close the dropdown menu when the dialog is closed?

sravimohan avatar Jun 15 '24 23:06 sravimohan

@Char99s, @shiftcontrol-dan, Using "preventDefault" works by keeping the dialog open. But it remains open even when the dialog is closed. Is there way to automatically close the dropdown menu when the dialog is closed?

Perhaps managing the open state of the dropdown, and then setting it to false once close the dialog.

shiftcontrol-dan avatar Jun 16 '24 05:06 shiftcontrol-dan

@Char99s, @shiftcontrol-dan, Using "preventDefault" works by keeping the dialog open. But it remains open even when the dialog is closed. Is there way to automatically close the dropdown menu when the dialog is closed?

+1

zhyd1997 avatar Jun 25 '24 04:06 zhyd1997

If you want to have a DialogBox pop up from a dropdown menu (for example, a dropdown menu to edit a user, which would pop up a DialogBox modal to edit it), you'll have to do it like this:

<DialogTrigger asChild>
      <DropdownMenuItem onSelect={(e) => e.preventDefault()}>Edit</DropdownMenuItem>
</DialogTrigger>

the key is the preventDefault() call.

Thank you, your solution worked really well for me; I was frustrated with the code unable to figure out why?? then like savior this helped me a lot

InsafNilam avatar Jun 27 '24 09:06 InsafNilam

ShadCn has provided also some guidance in the Dialog Page - here.

In cases of multiple different dialogs, you would need to tell react which dialog to render

  export function HeaderDropDownMenu() {
    const [dialogMenu, setDialogMenu] = useState<string>("none");
  
    const handleDialogMenu = (): JSX.Element | null => {
      switch (dialogMenu) {
        case "create":
          return <CreateDialog />
        case "delete":
          return <DeleteDialog />;
        default:
          return null;
      }
    };
  
    return (
      <Dialog>
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button size="icon" variant="ghost"> Menu </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent className="w-56">
            <DropdownMenuGroup>
              <DropdownMenuItem onSelect={() => setDialogMenu("create")}>
                <PlusIcon /> Create Campaign
              </DropdownMenuItem>
              <DropdownMenuItem onSelect={() => setDialogMenu("delete")}>
                <TrashIcon /> Delete Campaign
              </DropdownMenuItem>
            </DropdownMenuGroup>
          </DropdownMenuContent>
        </DropdownMenu>
        {handleDialogMenu()}
      </Dialog>
    );
 }

And your DeleteDialog should only contain the <DialogContent/> as you've already the entire component wrapped in a dialog.

export function DeleteCampaignDialog() {
  return (
    <DialogContent>
      <DialogHeader>
        <DialogTitle>DELETE</DialogTitle>
        <DialogDescription>
          This action cannot be undone. Are you sure you want to permanently
          delete this file from our servers?
        </DialogDescription>
      </DialogHeader>
      <DialogFooter>
        <Button type="submit">Confirm</Button>
      </DialogFooter>
    </DialogContent>
  );
}

lapatarka avatar Jul 29 '24 21:07 lapatarka