Shadcn ui Alert dialog closes automatically when clicking the trigger from dropdown menu

1.5k views Asked by At

So I know this is a problem other people have had but the all used the alert dialog in the same file. I try to open the alert dialog with "<DelteAlertDialog />" and have a dropdownmenuitem in there with delete.

This is the dropdown menu where i tried to open the alert dialog with it does open but just for 1 ms

      return (
        <DropdownMenu>
          <DropdownMenuTrigger>
            <Button variant="ghost" className="h-8 w-8 p-0">
              <span className="sr-only">Open menu</span>
              <MoreHorizontal className="h-4 w-4" />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end">
            <DropdownMenuLabel>Actions</DropdownMenuLabel>
            <DropdownMenuItem
              onClick={() => navigator.clipboard.writeText(entry.email)}
            >
              Copy Email
            </DropdownMenuItem>
            <DropdownMenuItem
              onClick={() => navigator.clipboard.writeText(entry.phone)}
            >
              Copy Phone number
            </DropdownMenuItem>
            <DropdownMenuSeparator />
            <DropdownMenuLabel>Manage</DropdownMenuLabel>
            <DropdownMenuItem 
              onClick={() => viewCV(entry)}
            >
              View cv
            </DropdownMenuItem>
            <DropdownMenuItem>Share cv</DropdownMenuItem>
            <DeleteAlertDialog entry={entry} />
          </DropdownMenuContent>
        </DropdownMenu>
      )

This is the alert dialog

export function DeleteAlertDialog({ entry }: { entry: Entry }) {
    const router = useRouter();
    return (
      <AlertDialog>
        <AlertDialogTrigger>
          <DropdownMenuItem>
            Delete
          </DropdownMenuItem>
        </AlertDialogTrigger>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
            <AlertDialogDescription>
              This action cannot be undone. This will permanently delete the
              the data from the server.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>Cancel</AlertDialogCancel>
            <AlertDialogAction
              onClick={async() => {
                await deleteEntry(entry)
                router.refresh()
              }}
            >
              Delete
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    )
  }
1

There are 1 answers

0
Balthazar PELLETIER On

One solution would be to get your AlertDialog out of the DropDown if you want to keep these in two different files. If you keep the dialog inside the dropdown content, it will unmount with the dropdown content on click.

Shadcn Dialogs are built on radix UI primitives, and the radix alert dialog provides an 'open' prop that allows you to control the opening and closing of dialogs without using 'AlertDialogTrigger'. This feature works the same for shadcn components. radix dialog doc

your alertDialog component could look something like that by ading open prop and removing the DialogTrigger :

export function DeleteAlertDialog({ entry, open }: { entry: Entry, open: boolean }) {
const router = useRouter();

return (
  <AlertDialog open={open}>
    <AlertDialogContent>
      <AlertDialogHeader>
        <AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
        <AlertDialogDescription>
          This action cannot be undone. This will permanently delete the
          the data from the server.
        </AlertDialogDescription>
      </AlertDialogHeader>
      <AlertDialogFooter>
        <AlertDialogCancel>Cancel</AlertDialogCancel>
        <AlertDialogAction
          onClick={async() => {
            await deleteEntry(entry)
            router.refresh()
          }}
        >
          Delete
        </AlertDialogAction>
      </AlertDialogFooter>
    </AlertDialogContent>
  </AlertDialog>
)

}

and your dropDown something like that (by adding a dropDown element 'delete' with an onClick handler changing the open state and passing it to the AlertDialog component):

    const [open, setOpen] = useState(false);

return (
  <>
    <DropdownMenu>
      <DropdownMenuTrigger>
        <Button variant="ghost" className="h-8 w-8 p-0">
          <span className="sr-only">Open menu</span>
          <MoreHorizontal className="h-4 w-4" />
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent align="end">
        <DropdownMenuLabel>Actions</DropdownMenuLabel>
        <DropdownMenuItem
          onClick={() => navigator.clipboard.writeText(entry.email)}
        >
          Copy Email
        </DropdownMenuItem>
        <DropdownMenuItem
          onClick={() => navigator.clipboard.writeText(entry.phone)}
        >
          Copy Phone number
        </DropdownMenuItem>
        <DropdownMenuSeparator />
        <DropdownMenuLabel>Manage</DropdownMenuLabel>
        <DropdownMenuItem 
          onClick={() => viewCV(entry)}
        >
          View cv
        </DropdownMenuItem>
        <DropdownMenuItem>Share cv</DropdownMenuItem>
        <DropdownMenuItem onClick={() => setOpen(true)}>Delete</DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
    <DeleteAlertDialog entry={entry} open={open}/>
  </>
)