Logo

dev-resources.site

for different kinds of informations.

Easy Forms for VueJS with Formspree

Published at
4/19/2024
Categories
vue
formspree
javascript
forms
Author
ninjasoards
Categories
4 categories in total
vue
open
formspree
open
javascript
open
forms
open
Author
11 person written this
ninjasoards
open
Easy Forms for VueJS with Formspree

Add a Contact Form to Your Vue or Nuxt App

Recently, I decided to consolidate some accounts by moving my domain registrations from Namecheap to Cloudflare and moving my static generated websites from Netlify to Cloudflare as well.

It was all pretty painless, but a few weeks later it dawned on me that I had been using Netlify Forms for the contact form on my portfolio site, and I hadn't bothered to change that code, so the form was broken.

Cloudflare doesn't have a 1:1 replacement for that feature but in their docs they have a few examples using Formspree, so I decided to give that service a try. Formspree has a generous free tier with up to 50 messages a month, which is more than enough for my needs.

Options API version

The Formspree docs have examples using HMTL, AJAX, and React (there's also an official React wrapper), but no example for VueJS. Below is what I am using in my Nuxt 2 app.

export default {
  name: 'Contact',
  data() {
    return {
      status: '',
    };
  },
  methods: {
    async handleSubmit(e) {
      try {
        const data = new FormData(e.target);
        const res = await fetch('https://formspree.io/f/<YOUR ENDPOINT>', {
          method: 'POST',
          body: data,
          headers: { Accept: 'application/json' },
        });
        if (res.ok) {
          this.status = "Thanks! I'll get back to you soon.";
          this.$refs.contactForm.reset();
          setTimeout(() => {
            this.status = '';
          }, 5000);
        } else {
          const json = await res.json();
          if (Object.hasOwn(json, 'errors')) {
            const errors = json.errors.map((error) => error.message).join(', ');
            throw new Error(errors);
          } else {
            throw new Error('Uh-oh! There was a problem submitting your form.');
          }
        }
      } catch (err) {
        console.error(err);
        this.status = err.message;
      }
    },
  },
};
Enter fullscreen mode Exit fullscreen mode
<p v-if="status">{{ status }}</p>
<form v-else ref="contactForm" name="contactme" @submit.prevent="handleSubmit">
  <label>
    Name
    <input id="name" name="name" type="text" required />
  </label>
  <label>
    Email
    <input id="email" name="email" type="email" required />
  </label>
  <label>
    Message
    <textarea id="message" name="message" required></textarea>
  </label>
  <label class="hidden">Don't fill this out: <input name="_gotcha" /></label>
  <button type="submit">Send Message</button>
</form>
Enter fullscreen mode Exit fullscreen mode

And so far, it's working great! Notice I also added a hidden "honeypot" input. Any form submitted with a filled in "_gotcha" input will be silently ignored by Formspree.

Composition API version

My portfolio site is static generated and I see no good reason to spend time updating it to Nuxt/Vue 3, but if I did I would definitely use Composition API and the code would look more like this:

// use script setup
const status = ref('');
const contactForm = ref(null);

async function handleSubmit(e) {
  try {
    const data = new FormData(e.target);
    const res = await fetch('https://formspree.io/f/<YOUR ENDPOINT>', {
      method: 'POST',
      body: data,
      headers: { Accept: 'application/json' },
    });
    if (res.ok) {
      status.value = "Thanks! I'll get back to you soon.";
      contactForm.value.reset();
      setTimeout(() => {
        status.value = '';
      }, 5000);
    } else {
      const json = await res.json();
      if (Object.hasOwn(json, 'errors')) {
        const errors = json.errors.map((error) => error.message).join(', ');
        throw new Error(errors);
      } else {
        throw new Error('Uh-oh! There was a problem submitting your form.');
      }
    }
  } catch (err) {
    console.error(err);
    status.value = err.message;
  }
},
Enter fullscreen mode Exit fullscreen mode
forms Article's
30 articles in total
Favicon
Shared form with config files in NextJs
Favicon
Building a Wedding Website with Next.js, Supabase, and Tailwind CSS
Favicon
Mastering Form Error Handling in Angular: Mapping Errors to User-Friendly Messages
Favicon
React: Optimizing Forms with Controlled and Uncontrolled Components
Favicon
How To Solve The Problem of the Vanishing PDF Form Data
Favicon
A Web Component for Conditional Dependent Fields
Favicon
Angular Typed Forms: Precision and Power in Form Management
Favicon
Requirement Rules for Checkboxes
Favicon
Using forms to create AI tools
Favicon
React-Hook-Form vs Formik: The Good, Bad, and Ugly
Favicon
Angular Form Architecture: Achieving Separation of Concerns with a FormHandlerService
Favicon
Simplifying Error Handling in Angular Forms with a Custom Directive
Favicon
Inaccessible forms
Favicon
Vue 3 Forms and Validations with VueFormify and yup
Favicon
Embed a form builder with Swift
Favicon
Uploading Files with React (POST Request)
Favicon
Easy Forms for VueJS with Formspree
Favicon
Guide to building fillable forms into your app
Favicon
Embed a form builder with Angular
Favicon
Angular Reactive Forms Basics
Favicon
Integrating Yii3 packages into WordPress
Favicon
Reactive Validation Triggers in Angular Forms
Favicon
Embed a form builder with React
Favicon
List of useful tools & widgets for website to boost marketing
Favicon
Embed a form builder with Javascript
Favicon
Building a Dynamic Contact Form for Your Hugo Static Website
Favicon
Exploring the Pros and Cons of AuraQuantic
Favicon
Why you should stop using google forms in 2024?
Favicon
How to create static website form with FabForm
Favicon
How to html forms

Featured ones: