Forms not working with gridsome

Hi,

My site is workio.netlify.app which has two forms /* newsletter and /contact. Neither work, nor does routing. If I remove the /* newsletter form routing works but /contact still does not.

Any ideas?

Many thanks in advance

Allan Stewart

Hiya! :wave:t2:

Not sure what you mean by ā€œnor does routingā€ - you mean the response redirect from submitting the form?

I pulled up your site then curlā€™d it as well - hereā€™s what Iā€™m seeing. On static curl, your home page contains

<form name='newsletter' method='POST' action='/newsletter-thanks' class='mb-12'>
        <input type='hidden' name='form-name' value='newsletter' />

Which is a good sign. That tells me that you did correctly have a <form> with proper Netlify data attributes defined at time of build and the Netlify build correctly pulled those attributes out, added a hidden form-name input child field, and saved the html to serve statically to whoever loads the page (yay!)

But when I load the page in a browser and it executes the front-end code you have running (which I havenā€™t looked into very much; I have no idea what framework youā€™re running here), I see that the form above is gone and instead there is:

<form name="newsletter" method="POST" action="/newsletter-thanks"
  data-netlify="true" data-netlify-honeypot="bot-field-newsletter" class="mb-12">

So, based on a few factors, my intuition is telling me that your front-end framework/code actually replaced the form entirelyā€¦ which can actually work totally fine, youā€™re just missing a piece. First, your front-end code doesnā€™t need to add in the data-netlify fields - those are only for flagging the build-bot at build time. Exposing them at runtime can actually be bad if a malicious web-crawler reads data-netlify-honeypot and avoids that field, understanding that itā€™s a honeypot. So 1) remove the data-netlify fields from your dynamic runtime form (make sure theyā€™re still there in your static / build time site ā€“ this is critical). Then 2) add a hidden input field to your dynamic form to match the static-generated <input type=ā€œhiddenā€ name="form-name" value="____" /> field. E.g. it should exactly match <input type='hidden' name='form-name' value='newsletter' /> in this case.

See, even though a dynamically-generated form with the same action="/path" will post to the same URI as the static-generated one that the build-bot makes for you when you add a netlify attribute to a <form>, Netlify doesnā€™t know which actual form data table to route that data to unless the form-name field is submitted in conjunction with the rest of the form data. Without it, the form data goes nowhere :slight_smile:

I hope thatā€™s understandable and helpful!

ā€“
Jon

1 Like

Hey Jon,

Thanks so much for taking the time to do all of that - itā€™s very kind of you. So am I reading u right that form-name has to be === form-name, not just the name I choose.

Iā€™m using gridsome to build it to static, so itā€™s a Static Site Generator. Iā€™ve done it exactly as it says on this page: Add a form to Gridsome - Gridsome

Seems simple, but I canā€™t see why itā€™s not working, unless itā€™s that form-name thing?

Best wishes,

Allan

1 Like

No problem! Happy to help.

Cool! Havenā€™t seen Gridsome before - though Iā€™ve not done really anything with Vue before. Super interesting - I was presuming that the form that ultimately was on the page was executed per standard browser events. It looks like thatā€™s not the case; that the Vue front-end actually manually handles the form submission via the code they have in that articleā€¦ very different.

I think I have good news though? I gave that a good read and I think you just have to change one thing and the whole thing might work? See where it had you write:

  handleSubmit(e) {
    fetch('/', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: this.encode({
        'form-name': e.target.getAttribute('name'),
        ...this.formData,
      }),
    })
    .then(() => this.$router.push('/success'))
    .catch(error => alert(error))
  }

just change the '/' to the path you actually want to POST to. In this case, make it: /newsletter-thanks. And also make sure that you are using /newsletter-thanks where it has /success too. All in all, if you swap that block out for this, I think you may be in luck (for the newsletter form - you would need to modify for the other)

  handleSubmit(e) {
    fetch('/newsletter-thanks', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: this.encode({
        'form-name': e.target.getAttribute('name'),
        ...this.formData,
      }),
    })
    .then(() => this.$router.push('/newsletter-thanks'))
    .catch(error => alert(error))
  }
1 Like

Frankly, if that works for you like I think it should, I would suggest you send a message to GridSome and ask them to update their docs. Having a pre-baked way to integrate a form into Netlify that doesnā€™t wire it up right is cause for pain for everyone :slightly_frowning_face:

1 Like

Terrific, thankyou again. Iā€™m really looking forward to testing this out tomorrow, as I would love to use netlify forms rather than something else like formspree as itā€™s nice to keep a tight stack.

If it works as we hope then I will 100% be sending gridsome an email to update this. And Jon if you work for Netlify then you would likely have more luck than me as you have a tonne of customers gridsome would want to keep happy.

Cheers again,

Allan

Hi again Jon,

I tested it today and made some progress here https://determined-mestorf-125a22.netlify.app/

The contact form works perfectly but the newsletter one doesnā€™t seem to make its way to the forms part of the netlify admin.

Iā€™ve tried lots of deployments/different tests but it doesnā€™t seem to want to work.

Hm. Your app link is no longer valid as far as I can tell so I canā€™t poke around, but for debugging purposes, can you paste in this thread the following?

  1. The static build-time <form> HTML with the associated data-netlify-etc tags included for the contact form
  2. The handleSubmit function code for the contact form
  3. The static build-time <form> HTML with the associated data-netlify-etc tags included for the newsletter form
  4. The handleSubmit function code for the newsletter form

Should be able to figure out whatā€™s going on between those four things.

Hi Jon,

Oh sorry yes, I did some more work after it - up to about 20 hours now - urgh :frowning:
Thanks so much for continuing to help. Iā€™ve pasted the code below and the website is here: https://sad-brattain-86e55d.netlify.app/

Hopefully when we figure it out its something we can write back into the Gridsome documents so other users donā€™t suffer.

Code below but I also put into code bin incase thats easier to debug:

https://codepen.io/stewdog79-the-decoder/pen/mdeqvqX ā† Contact Working
https://codepen.io/stewdog79-the-decoder/pen/YzyEBYr ā† Newsletter Not Working

Contact Form

<form name="contact" method="POST" v-on:submit.prevent="handleSubmit" action="/contact-thanks" data-netlify="true" data-netlify-honeypot="bot-field" class="mb-12">

              <!-- Name & Email -->

              <div class="flex flex-wrap mb-6 -mx-4">

                <div class="w-full md:w-1/2 mb-6 md:mb-0 px-4">

                  <input type="hidden" name="form-name" value="contact" />

                  <p hidden>

                    <label>No no no:<input name="bot-field" /></label>

                  </p>

                  <label for="name" class="block mb-2 text-copy-primary">Your name</label>

                  <input

                    type="text"

                    name="name"

                    v-model="formData.name"

                    id="name"

                    placeholder="Jon Snow"

                    class="block w-full bg-background-form border border-border-color-primary shadow rounded outline-none focus:border-ink-400 mb-2 p-4"

                    required

                  />

                </div>

                <div class="w-full px-4 md:w-1/2">

                  <label for="email" class="block text-copy-primary mb-2">Your email</label>

                  <input

                    type="email"

                    name="email"

                    v-model="formData.email"

                    id="email"

                    placeholder="email@example.com"

                    class="block w-full bg-background-form border border-border-color-primary shadow rounded outline-none focus:border-ink-400 mb-2 p-4"

                    required

                  />

                </div>

              </div>

              <!-- Message -->

              <div class="w-full mb-12">

                <label class="block text-copy-primary mb-2" for="message">Message</label>

                <textarea

                  id="message"

                  rows="5"

                  name="message"

                  v-model="formData.message"

                  class="block w-full bg-background-form border border-border-color-primary shadow rounded outline-none appearance-none focus:border-ink-400 mb-2 px-4 py-4"

                  placeholder="Enter your message here."

                  required

                >

                </textarea>

              </div>

              <!-- Send -->

              <div class="flex justify-end w-full">

                <button type="submit" class="block bg-ink-400 hover:bg-peach-400 text-white text-sm font-semibold tracking-wide uppercase shadow rounded cursor-pointer px-6 py-3">

                  Send

                </button>

              </div>

            </form>

Then the function

export default {

  metaInfo: {

    title: "Contact Us",

  },

  data() {

    return {

      formData: {},

    }

  },

  methods: {

    encode(data) {

      return Object.keys(data)

        .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))

        .join('&')

    },

    handleSubmit(e) {

      fetch('/contact-thanks', {

        method: 'POST',

        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },

        body: this.encode({

          'form-name': e.target.getAttribute('name'),

          ...this.formData,

        }),

      })

      .then(() => this.$router.push('/contact-thanks'))

      .catch(error => alert(error))

    }

  }

};

Newsletter

<form name="newsletter" method="POST" v-on:submit.prevent="handleSubmit" action="/poo" data-netlify="true" data-netlify-honeypot="bot-field" class="mb-12">

          <div class="flex flex-col sm:flex-row">

            <input type="hidden" name="form-name" value="newsletter" />

            <p hidden>

              <label>No no no:<input name="bot-field" /></label>

            </p>

            <input

              type="email"

              name="newsletter"

              v-model="testing.newsletter"

              id="newsletter"

              placeholder="Your email address"

              class="flex-1 bg-background-form rounded sm:rounded-r-none px-4 py-4 leading-normal border border-border-color-primary sm:border-r-0 shadow outline-none focus:border-ink-400 z-10"

              required

            />

            <button

              type="submit"

              class="flex-2 w-40 uppercase bg-ink-400 text-white rounded sm:rounded-l-none text-lg py-3 px-8 tracking-wide shadow focus:outline-none hover:bg-peach-400 focus:bg-peach-400 z-10 w-full sm:w-auto mt-4 sm:mt-0"

            >

              <span>Subscribe</span>

            </button>

          </div>

        </form>

And the functions

export default {

  data() {

    return {

      testing: {},

    }

  },

  methods: {

    encode(data) {

      return Object.keys(data)

        .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))

        .join('&')

    },

    handleSubmit(e) {

    fetch('/thanks', {

      method: 'POST',

      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },

      body: this.encode({

        'form-name': e.target.getAttribute('newsletter'),

        ...this.testing,

      }),

    })

    .then(() => this.$router.push('/thanks'))

    .catch(error => alert(error))

    }

  }

};

Hey @workio, Iā€™m really sorry to hear about your form woes :frowning: definitely sounds like we should PR those Gridsome docs. I wanted to touch base about where things are at now. I do see both forms in your Netlify UI :partying_face: Does that mean you got this working?

1 Like

Hi Jen,

Thanks so much for checking in on me. It all seems to work, but nothing ever makes it into the netlify admin area. Itā€™s very strange indeed and I donā€™t know how to debug it as Iā€™ve not got any errors and it all seems fine. It even passed my mind that maybe netlify donā€™t allow just email sub forms u might have to also have a name or something.

Very lostā€¦ Any help u might be able to offer would be terrific.

Best wishes

Allan

1 Like

Hi @jen and @jonsully any tips for me - the newletter form is still not working.

Hey @Workio!

Apologies for leaving you hanging there a bit. Busy times :slight_smile:

I just reviewed the two Code pens you posted 7 days ago. Are they still valid and reflective of the code youā€™re running? Letā€™s dig into this thangā€™ :smiling_imp:



Hey as a quick side-note, any time you use code blocks on Netlify (or any Markdown interface) and you use the three back-ticks to indicate the start and end of the block, you can actually put in the language name after the opening three ticks and it will render that code with proper syntax highlighting for that language. Super helpful. Example:

```html
<div class="hello-world">
`` `

(donā€™t put that space in the last ticks, I just had to because Iā€™m showing backticks inside of backticksā€¦

Example js:

```js
const foo = ['123', 123, foo]
`` `

Highlighted syntax is extremely helpful for us to quickly read and parse your code :slight_smile:

Hey @jonsully

yeah all still the exact same. Hope they are ok for you to help me - and again, its a massive appreciation from me for this help.

I will go back now and edit those posts and put in the language syntax highlighting.

Look forwards to hearing and please do let me know if thereā€™s anything else I can provide.

Best wishes,

Allan

I think it may be the action="/poo" in your ā€œNewsletter Not Workingā€ Codepen :wink: the action on the form should match the POST target in the Javascript, so /thanks in this case

ā€“
Jon

1 Like

Hi @jonsully and @jen - so sorry to bother you again, but Iā€™m still having trouble getting this form to work. As a reminder, Iā€™m using Gridsome and have been following their guidelines here Add a form to Gridsome - Gridsome. It all ā€œseemsā€ to be working, with the action page loading, but Iā€™ve noticed that my fetch is giving a 404 error, its so strange. Iā€™ve attached an image, highlighted bits of interest in yellow, that shows both the action page loaded on the left, and the strange 404ā€™s, null form name data on the right -

The /contact form work like a dream! Just this one I canā€™t understand why not.

Iā€™ve redeployed the site again just in case it was that here it is https://jolly-neumann-c33b48.netlify.app/

The code Iā€™m using is below with the correct vue syntax highlighting this time.

** Many weeks of work now trying to fix it. Really really hugely appreciate any help.**

<template>
  <div class="newsletter bg-background-tertiary">
    <div class="container-inner mx-auto py-16 pb-8 text-center textl-xl">
      <h2 class="mb-8">Join the Workio Newsletter</h2>

      <div class="w-4/5 mx-auto mb-8">
        <p class="mb-8 text-lg sm:text-xl">
          Special offers, new blog posts, industry research, and product update alerts. Be the first to know.
        </p>

        <form name="newsletter" method="POST" v-on:submit.prevent="handleSubmit" action="/newsletter-thanks" data-netlify="true" data-netlify-honeypot="bot-field" class="mb-12">
          <div class="flex flex-col sm:flex-row">
            <input type="hidden" name="form-name" value="newsletter" />
            <p hidden>
              <label>No no no:<input name="bot-field" /></label>
            </p>
            <input
              type="email"
              name="email"
              v-model="formData.email"
              id="email"
              placeholder="Your email address"
              class="flex-1 bg-background-form rounded sm:rounded-r-none px-4 py-4 leading-normal border border-border-color-primary sm:border-r-0 shadow outline-none focus:border-ink-400 z-10"
              required
            />
            <button
              type="submit"
              class="flex-2 w-40 uppercase bg-ink-400 text-white rounded sm:rounded-l-none text-lg py-3 px-8 tracking-wide shadow focus:outline-none hover:bg-peach-400 focus:bg-peach-400 z-10 w-full sm:w-auto mt-4 sm:mt-0"
            >
              <span>Subscribe</span>
            </button>
          </div>
        </form>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      formData: {},
    };
  },
  methods: {
    encode(data) {
      return Object.keys(data)
        .map((key) => encodeURIComponent(key) + "=" + encodeURIComponent(data[key]))
        .join("&");
    },
    handleSubmit(e) {
      fetch("/newsletter-thanks", {
        method: "POST",
        headers: { "Content-Type": "application/x-www-form-urlencoded" },
        body: this.encode({
          "form-name": e.target.getAttribute("email"),
          ...this.formData,
        }),
      })
        .then(() => this.$router.push("/newsletter-thanks"))
        .catch((error) => alert(error));
    },
  },
};
</script>

Checking this out again (ignore the test submission from me!)ā€¦

Could you try adding <label for="email"></label> tags before your email input? And could you also please drop your encoding function in here again? Really sorry youā€™ve been struggling with this for weeks :frowning:

Hi @jen,

Thanks for your reply. Iā€™ve had to put the site live now and its available at https://www.workio.co/ - as you will see I tried adding the label, but unfortunately it is still not working.

The whole vue component + the encoding function is here again. Any ideas?

<template>
  <div class="newsletter bg-background-tertiary">
    <div class="container-inner mx-auto py-16 pb-8 text-center textl-xl">
      <h2 class="mb-8">Join the Workio Newsletter</h2>

      <div class="w-4/5 mx-auto mb-8">
        <p class="mb-8 text-lg sm:text-xl">
          Special offers, new blog posts, industry research, and product update alerts. Be the first to know.
        </p>

        <form name="newsletter" method="POST" v-on:submit.prevent="handleSubmit" action="/newsletter-thanks" data-netlify="true" data-netlify-honeypot="bot-field" class="mb-12">
          <div class="flex flex-col sm:flex-row">
            <input type="hidden" name="form-name" value="newsletter" />
            <p hidden>
              <label>No no no:<input name="bot-field" /></label>
            </p>
            <label for="email"></label>
            <input
              type="email"
              name="email"
              v-model="formData.email"
              id="email"
              placeholder="Your email address"
              class="flex-1 bg-background-form rounded sm:rounded-r-none px-4 py-4 leading-normal border border-border-color-primary sm:border-r-0 shadow outline-none focus:border-ink-400 z-10"
              required
            />
            <button
              type="submit"
              class="flex-2 w-40 uppercase bg-ink-400 text-white rounded sm:rounded-l-none text-lg py-3 px-8 tracking-wide shadow focus:outline-none hover:bg-peach-400 focus:bg-peach-400 z-10 w-full sm:w-auto mt-4 sm:mt-0"
            >
              <span>Subscribe</span>
            </button>
          </div>
        </form>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      formData: {},
    };
  },
  methods: {
    encode(data) {
      return Object.keys(data)
        .map((key) => encodeURIComponent(key) + "=" + encodeURIComponent(data[key]))
        .join("&");
    },
    handleSubmit(e) {
      fetch("/newsletter-thanks", {
        method: "POST",
        headers: { "Content-Type": "application/x-www-form-urlencoded" },
        body: this.encode({
          "form-name": e.target.getAttribute("email"),
          ...this.formData,
        }),
      })
        .then(() => this.$router.push("/newsletter-thanks"))
        .catch((error) => alert(error));
    },
  },
};
</script>

Hi @jen

Iā€™ve figured it out (partly) eureka!

I believe that the code that Iā€™ve used from the gridsome website doesnā€™t handle only one array element well. I say that as when I add in the below it works fine.

<label for="name" class="block mb-2 text-copy-primary"></label>
            <input
              type="hidden"
              name="name"
              v-model="formData.name"
              id="name"
              placeholder="New Subscriber"
              class="flex-1 bg-background-form rounded sm:rounded-r-none px-4 py-4 leading-normal border border-border-color-primary sm:border-r-0 shadow outline-none focus:border-ink-400 z-10 mr-2"
              required
            />

I suspect the reason for this is the use of a spread opperator ā€¦this.formData as I beleive thats saying ā€œand passing in all the other array elements into this.encodeā€. Endone(data) has a .join(ā€™&ā€™) meaning its appending an & at the end of every array ellement. I suspect this combination of single field forms + spread opperator + .join is not working. At least this is my understanding of the code.

I suspect removing the spread and join for now would fix it in a more elegant way, but my ā€œhacky bodgeā€ of pushing a hidden name field works so I donā€™t want to spend more time on it.

The other theory I have is that netlify needs a minimum of 2 fields to process a form.

Testing is incredibly painful on netlift forms as you have to redeploy over and over again, which takes forever and is sole destroying.

I have added this post for the following reasons

  1. To help anyone else who might have similar issues does need to waste weeks and weeks of time.
  2. So that anyone smarter or with more time than me can 100% confirm the exact problem, why and an elegant fix.
  3. So that gridsome and/or netlify might be able to make a small improvement to either their code docs or if netlift, their form system (depending on item 2 above)
  4. As I wonder if there might be a faster and easier way for devs to debug netlifty forms in a more practical local host way.

Anyway, for now Im happy its working!

Fingers crossed you figure out the exact issues and can help make a better fix.

Thanks everyone who helped me on this thread and if you read this cos its issue for you too - good luck!

Cheers

Allan

2 Likes