ui icon indicating copy to clipboard operation
ui copied to clipboard

Dialog and Input strange behaviour - input value overwrite

Open premiare opened this issue 1 year ago • 1 comments

I have a Dialog with Inputs inside of it, when typing in the inputs everything is fine except when moving the mouse while typing. This causes some weird effect which highlights the current value and inherently clearing the input field.

I have separate sheet component (which is a Dialog under the hood) and there's no issues.

https://www.loom.com/share/4da33593b3124313bfb837ff0f5393cf?sid=605db76b-31f9-4b64-be4e-45ada3a24021

I also had another issue where the inputs weren't allowing spacebar key presses as characters, that's why the onKeyDown function is on the DialogContent

Pretty standard Dialog, nothing crazy.

      <Dialog
        open={open}
        onOpenChange={() => {
          if (!open) {
            setOpen(true);
          } else {
            handleClose();
          }
        }}
      >
        <DialogTrigger asChild>
          <Button variant="default" className="gap-2">
            <Plus className="h-6 w-6" />
            Add Contact
          </Button>
        </DialogTrigger>
        <DialogContent onKeyDown={(e) => e.stopPropagation()}>
          <DialogHeader>
            <h2 className="text-2xl font-semibold">Add Contact</h2>
          </DialogHeader>
          <Form {...form}>
            <form onSubmit={form.handleSubmit(onSubmit)} className="w-full">
              <FormRow>
                <FormField
                  control={form.control}
                  name="company"
                  render={({ field }) => (
                    <FormItem className="w-full">
                      <FormLabel>Company</FormLabel>
                      <Autocomplete
                        field={field}
                        emptyMessage="Womp womp"
                        placeholder="Search company..."
                        options={companies.map((company) => ({
                          value: company.company,
                          label: company.company,
                        }))}
                      />
                    </FormItem>
                  )}
                />
              </FormRow>
              <FormRow>
                <FormField
                  control={form.control}
                  name="first_name"
                  render={({ field }) => (
                    <FormItem className="w-full">
                      <FormLabel>First Name</FormLabel>
                      <FormControl>
                        <Input placeholder="First Name" {...field} />
                      </FormControl>
                    </FormItem>
                  )}
                />
                <FormField
                  control={form.control}
                  name="last_name"
                  render={({ field }) => (
                    <FormItem className="w-full">
                      <FormLabel>Last Name</FormLabel>
                      <FormControl>
                        <Input placeholder="Last Name" {...field} />
                      </FormControl>
                    </FormItem>
                  )}
                />
              </FormRow>
              <FormRow>
                <FormField
                  control={form.control}
                  name="email"
                  render={({ field }) => (
                    <FormItem className="w-full">
                      <FormLabel>Email</FormLabel>
                      <FormControl>
                        <Input placeholder="Email" {...field} />
                      </FormControl>
                    </FormItem>
                  )}
                />
              </FormRow>
              <FormRow>
                <FormField
                  control={form.control}
                  name="mobile"
                  render={({ field }) => (
                    <FormItem className="w-full">
                      <FormLabel>Mobile</FormLabel>
                      <FormControl>
                        <Input
                          placeholder="Mobile Phone (e.g., 0412345678)"
                          {...field}
                          type="tel"
                          pattern="04[0-9]{2}[0-9]{3}[0-9]{3}"
                          title="Format: 04XXXXXXXX"
                        />
                      </FormControl>
                    </FormItem>
                  )}
                />
                <FormField
                  control={form.control}
                  name="work_phone"
                  render={({ field }) => (
                    <FormItem className="w-full">
                      <FormLabel>Work Phone</FormLabel>
                      <FormControl>
                        <Input
                          placeholder="Work Phone"
                          {...field}
                          type="tel"
                          pattern="\([0][2-9]\)[0-9]{4}[0-9]{4}"
                          title="Format: (0X)XXXXXXXX"
                        />
                      </FormControl>
                    </FormItem>
                  )}
                />
              </FormRow>
              <FormRow>
                <FormField
                  control={form.control}
                  name="role"
                  render={({ field }) => (
                    <RoleSelect
                      field={field}
                      placeholder="Select a role"
                      options={[
                        { label: "Purchasing", value: "Purchasing" },
                        {
                          label: "Purchaser/Billing",
                          value: "Purchaser/Billing",
                        },
                        {
                          label: "Billing",
                          value: "Billing",
                        },
                      ]}
                      label="Role"
                      defaultValue={field.value || "Select a role"}
                    />
                  )}
                />
              </FormRow>
              <FormRow>
                <FormField
                  control={form.control}
                  name="notes"
                  render={({ field }) => (
                    <FormItem className="w-full">
                      <FormLabel>Notes</FormLabel>
                      <FormControl>
                        <Textarea
                          placeholder="Notes"
                          {...field}
                          value={field.value || ""}
                        />
                      </FormControl>
                    </FormItem>
                  )}
                />
              </FormRow>
              <FormRow>
                <Button type="submit" className="w-full">
                  Save
                </Button>
              </FormRow>
            </form>
          </Form>
          <span className="font-mono flex flex-col p-4 bg-slate-300">
            <>{JSON.stringify(form.watch(), null, 2)}</>
          </span>
        </DialogContent>
      </Dialog>

premiare avatar Jan 19 '24 12:01 premiare

I had similar issues when creating a component within the component.

If you happen to be doing something like this

function Component() {
  const MyDialog = () => (
     <Dialog>
     ...
     </Dialog>
     )
   
   return (
      <MyDialog />
    )
}

Try taking out the component or making the component inside like this

function Component() {
  const dialog = (
    <Dialog>
     ...
     </Dialog>
     )
   
   return (
      <>
      .... yourCode
      {dialog}
      </>
    )

This happens since you are recreating the inner component and it will reset the state in unexpected ways. Hope this helps.

yoalix avatar Jan 31 '24 23:01 yoalix

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 22 '24 23:02 shadcn

@premiare can you resolve this issue? I'm also facing this while using dialog inside a dropdown item.

kayumuzzaman avatar Jun 02 '24 17:06 kayumuzzaman

@premiare can you resolve this issue? I'm also facing this while using dialog inside a dropdown item.

This issue was a while ago, but I think to resolve my issue I created a "Form" component and used that inside of the Dialog, rather than each individual input etc.

For your issue, perhaps the DialogTrigger needs the asChild param

premiare avatar Jun 03 '24 01:06 premiare

I had the same problem here. I have a data table, and I also have a dropdown in every row. That dropdown has a button which opens a dialog with a form.

I fixed this issue adding:

<DialogContent onClick={(e) => e.stopPropagation()} onKeyDown={(e) => e.stopPropagation()} onPointerMove={(e) => e.stopPropagation()}

That fixed the issue when typing and moving the mouse while typing.

Now I'm facing the same issue when the mouse is outside the div of the form and is placed in the black background div.

If I solve the issue, I will post again.

EDIT: I fixed it adding the same in <DialogPrimitive.Overlay>

<DialogPrimitive.Overlay ref={ref} onPointerMove={(e) => e.stopPropagation()}

alejanfh avatar Jul 01 '24 08:07 alejanfh

onPointerMove={(e) => e.stopPropagation()}

Thanks!

But is there a less hacky way to do so?

zacBkh avatar Jul 17 '24 15:07 zacBkh

in my case, need to use both asChild & stopPropagation() as I've multi layer.

kayumuzzaman avatar Jul 17 '24 19:07 kayumuzzaman