Search code examples
javascriptvue.jsnetlifynetlify-function

"Cannot POST /" in Vue (Gridsome) App - Netlify Forms prevent redirect


I am building a personal website with Gridsome. I am trying to set up a newsletter signup form via Netlify Forms. I don't want the user to be redirected after clicking 'Submit'. To prevent that I use @submit.prevent like so:

<form name= "add-subscriber" id="myForm" method="post" @submit.prevent="handleFormSubmit" 
data-netlify="true" data-netlify-honeypot="bot-field">
  <input type="hidden" name="form-name" value="add-subscriber" />
  <input type="email" v-model="formData.userEmail" name="user_email" required="" id="id_user_email">
  <button type="submit" name="button">Subscribe</button>
</form>

Then using a mix of the following guides (gridsome guide, CSS-Tricks guide) I do the following in my script section:

<script>
import axios from "axios";

export default {
    data() {
        return {
            formData: {},
            }
        },

    methods: {
        encode(data) {
            return Object.keys(data)
            .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
            .join('&')
        },

        handleFormSubmit(e) {
            axios('/', {
                method: 'POST',
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                body: this.encode({
                    'form-name': e.target.getAttribute('name'),
                    ...this.formData,
                }),
            })
            .then(() => this.innerHTML = `<div class="form--success">Almost there! Check your inbox for a confirmation e-mail.</div>`)
            .catch(error => alert(error))
        }
    }
}
</script>

Error

Whatever I try I can't figure out how to configure the desired behavior. I keep getting the following errors - > Error: Request failed with status code 404 & Cannot POST /

Note

The reason I want to do it this way is that after the user submits the form a Netlify Function will be called to send the email_adress to EmailOctopus via their API.

This is how the function looks like:

submissions-created.js

import axios from "axios";

exports.handler = async function(event) {
    console.log(event.body)
    const email = JSON.parse(event.body).payload.userEmail
    console.log(`Recieved a submission: ${email}`)

    axios({
        method: 'POST',
        url: `https://emailoctopus.com/api/1.5/lists/contacts`,
        data: {
            "api_key": apikey,
            "email_address":  email,
        },
    })
    .then(response => response.json())
    .then(data => {
        console.log(`Submitted to EmailOctopus:\n ${data}`)
    })
    .catch(function (error) {
        error => ({ statusCode: 422, body: String(error) })
    });
}

Sorry for the long question. I really apreciate your time and your help. If you need any further details please let me know.


Solution

  • You can see the functional implementation in my repo (https://github.com/rasulkireev/gridsome-personal-webite). These are the changes I made.

    submission-created.js

    var axios = require("axios")
    
    exports.handler = async function(event, context) {
    
        const email = JSON.parse(event.body).payload.email
        console.log(`Recieved a submission: ${email}`)
    
        return await axios({
            method: 'POST',
            url: 'https://api.buttondown.email/v1/subscribers',
            headers: {
                Authorization: `Token ${process.env.BUTTONDOWN_API}`
            },
            data: {
                'email': email,
            },
        })
        .then(response => console.log(response))
        .catch(error => console.log(error))
    }
    

    newsletter form in my components

     <div>
              <form
              name="add-subscriber"
              id="myForm"
              method="post"
              data-netlify="true"
              data-netlify-honeypot="bot-field"
              enctype="application/x-www-form-urlencoded"
              @submit.prevent="handleFormSubmit">
                <input type="hidden" name="form-name" value="add-subscriber" />
                <input type="email" name="userEmail" v-model="formData.userEmail">
                <button type="submit" name="button">Subscribe</button>
              </form>
            </div>
    

    with the following script code in the same component

    import axios from "axios";
    export default {
        props: ['title', 'description'],
        
        data() {
            return {
                formData: {
                    userEmail: null,
                },
            }
        },
        methods: {
            encode(data) {  
                const formData = new FormData();
                
                for (const key of Object.keys(data)) {
                    formData.append(key, data[key]);
                }
                
                return formData;
            },
            handleFormSubmit(e) {
                const axiosConfig = {
                    header: { "Content-Type": "application/x-www-form-urlencoded" }
                };
                axios.post(
                    location.href, 
                    this.encode({
                        'form-name': e.target.getAttribute("name"),
                        ...this.formData,
                    }),
                    axiosConfig
                )
                .then(data => console.log(data))
                .catch(error => console.log(error))
                .then(document.getElementById("myForm").innerHTML = `
                <div>Thank you! I received your submission.</div>
                `)
            }
        }
    }