radix-vue / shadcn-vue

Vue port of shadcn-ui
https://www.shadcn-vue.com/
MIT License
3.53k stars 204 forks source link

[Bug]: Form not submitting #558

Closed khawarizmus closed 1 month ago

khawarizmus commented 1 month ago

Reproduction

https://stackblitz.com/edit/nuxt-starter-ggrskg?file=app.vue

Describe the bug

I have followed the documentation step by step but so far I am unable to make the form submit. I have attached a reproduction link to showcase the problem.

But i will go ahead and past my original code for reference:

<template>
  <Dialog>
    <DialogTrigger as-child>
      <Button
        class="px-6 py-3 mt-6 text-xl font-normal text-white bg-black rounded-md md:self-end lg:self-start dark:text-slate-200 w-fit disabled:bg-gray-400 disabled:cursor-not-allowed hover:bg-gray-700"
      >
        {{ waitingText }}
      </Button>
    </DialogTrigger>

    <DialogContent :disable-outside-pointer-events="true" :trapFocus="true">
      <DialogHeader>
        <DialogTitle>Get notified when we launch</DialogTitle>
        <Form id="sabrListForm" class="space-y-6" @submit="submitHandler">
          <FormField name="email" v-slot="{ componentField }">
            <FormItem v-auto-animate>
              <FormLabel>
                {{ $t("modal.email") }}
              </FormLabel>
              <FormControl>
                <Input
                  type="email"
                  :placeholder="$t('modal.placeholder')"
                  v-bind="componentField"
                />
              </FormControl>
              <FormMessage />
            </FormItem>
          </FormField>
        </Form>
        <DialogDescription>
          <p>
            {{ $t("modal.privacy") }}
            <NuxtLink to="/privacy" class="underline cursor-pointer">{{
              $t("modal.policy")
            }}</NuxtLink>
          </p>
        </DialogDescription>

        <DialogFooter>
          <Button form="sabrListForm" type="submit">{{
            $t("modal.join")
          }}</Button>
        </DialogFooter>
      </DialogHeader>
    </DialogContent>
  </Dialog>
</template>

<script setup lang="ts">
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Form,
  FormField,
  FormItem,
  FormLabel,
  FormControl,
  FormMessage,
} from "@/components/ui/form";
import { useApiFetch } from "~/composables/useApiFetch";
import { vAutoAnimate } from "@formkit/auto-animate/vue";
import * as z from "zod";
import { toTypedSchema } from "@vee-validate/zod";

defineProps({
  waitingText: {
    type: String,
    required: true,
  },
});

const emitter = useEmitter();

let loading = ref(false);

const schema = z.object({
  email: z
    .string({
      required_error: "Email is required",
    })
    .email("Invalid email address"),
});

const { handleSubmit } = useForm({
  validationSchema: toTypedSchema(schema),
});

const submitHandler = handleSubmit(async (values) => {
  console.log("submitHandler");
  console.log(values);
  const { error, pending } = await useApiFetch("waitlist", {
    method: "POST",
    body: JSON.stringify(values?.email),
  });

  loading = pending;

  if (!error.value) {
    emitter.emit("success", {
      title: "You have been added to the patently waiting!",
    });
  } else {
    emitter.emit("error", {
      title: "Something went wrong",
      options: {
        description: error.value?.message || "Please try again later",
      },
    });
  }
});
</script>

System Info

System:
    OS: macOS 14.2.1
    CPU: (16) x64 Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
    Memory: 547.92 MB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.18.2 - ~/.nvm/versions/node/v18.18.2/bin/node
    Yarn: 1.22.19 - ~/.nvm/versions/node/v18.18.2/bin/yarn
    npm: 9.8.1 - ~/.nvm/versions/node/v18.18.2/bin/npm
    pnpm: 8.15.4 - ~/.nvm/versions/node/v18.18.2/bin/pnpm
    bun: 1.1.8 - ~/.bun/bin/bun
  Browsers:
    Chrome: 124.0.6367.208
    Safari: 17.2.1
  npmPackages:
    @vueuse/core: ^10.9.0 => 10.9.0 
    nuxt: ^3.5.0 => 3.11.2 
    radix-vue: ^1.7.4 => 1.7.4 
    shadcn-nuxt: ^0.10.4 => 0.10.4

Contributes

khawarizmus commented 1 month ago

Well it seems that the issue is that i was using the Form component instead of the form element.

Not sure if this is an expected behaviour but if it is then the documentation should fix the anatomy section.

If it isn't then the bug is still present and demo-able here where you have tow identical dialogues one works and the other one doesn't.

https://stackblitz.com/edit/nuxt-starter-ggrskg?file=app.vue

sadeghbarati commented 1 month ago

@khawarizmus Hi you are mixing two different ways together which it's not the best practices

While using <Form> component you don't need useForm composable and handleSubmit function, you just need to use <Form> component props like

<Form :validation-schema="schema" @submit="onSubmit">

If you are validation something inside Dialog component <Form> component is recommended

Related issue: https://github.com/radix-vue/shadcn-vue/issues/459

khawarizmus commented 1 month ago

Thank you it makes sense now