# Vue forms

A copy-paste Vue single-file component that submits a form to Nisuform with fetch, with spam protection and success and error states.

Collect the fields, `POST` them to your endpoint and check the response. You don't need a server or environment variables, because the form key is safe to publish. Using Nuxt? See [Nuxt forms](/docs/frameworks/nuxt).

<Callout title="Generated for your form">
  The form's **Setup** tab, under **Code**, has this component ready with your endpoint and field names filled in. **Your design** gives you the styled form from the builder as a component. **Your own styles** gives you a bare component to style your way.
</Callout>

## The component

```vue title="ContactForm.vue"
<script setup>
import { ref } from 'vue'

const shownAt = Date.now()
const status = ref('idle')

async function onSubmit(event) {
  status.value = 'sending'
  const data = new FormData(event.target)
  data.set('_elapsed', String(Date.now() - shownAt))
  const response = await fetch('https://api.nisuform.com/s/YOUR_FORM_KEY', {
    method: 'POST',
    headers: { Accept: 'application/json' },
    body: data,
  })
  status.value = response.ok ? 'sent' : 'error'
}
</script>

<template>
  <p v-if="status === 'sent'">Thanks! We got your message.</p>
  <form v-else @submit.prevent="onSubmit">
    <input type="email" name="email" placeholder="Email" required />
    <textarea name="message" rows="5" required></textarea>
    <input type="text" name="_gotcha" tabindex="-1" autocomplete="off" style="display: none" />
    <button type="submit" :disabled="status === 'sending'">Send</button>
    <p v-if="status === 'error'" role="alert">Something went wrong. Please try again.</p>
  </form>
</template>
```

## Use it

```vue title="App.vue"
<script setup>
import ContactForm from './components/ContactForm.vue'
</script>

<template>
  <ContactForm />
</template>
```

## What it does

* Sends `Accept: application/json`, so Nisuform answers with JSON instead of the thank-you page. See [JavaScript and fetch](/docs/connect/javascript).
* Adds `_elapsed`, the time the form was open, and keeps the hidden `_gotcha` honeypot empty. Both feed [spam protection](/docs/protection/spam). See [Special fields](/docs/connect/special-fields).
* Shows a success message when the submission is accepted, and an error when it isn't.
