Nuxt, Netlify forms and "failed to execute 'appendChild'"
by Maria Tsvetkova Sep 18, 2020

Nuxt, Netlify forms and "failed to execute 'appendChild'"

One day I had to make a tiny adjustment to the website - like adding a carousel, which is quite a trivial task which I've estimated for two hours - but spent several days on it.

The slider worked on dev build, worked locally with generated files, and worked even in a docker container with generated static HTML. However, on the demo and production servers I saw an error:

Failed to execute 'appendChild' on 'Node': This node type does not support this method.

The error prevented any javascript from working on the page, and I spent quite some time to find and fix it. A little bit of googling showed that the reason for the error was some invalid markup.

I took my generated page and validated it - it was valid. I now think I could take my markup from the server and validate it, but I decided to implement the Binary search:

1. Comment out half of the component HTML code, push it as see the build preview;

2. If the error persists - comment out half of the remaining code;

3. Repeat until you find the component causing it.

I figured out the error originated from the contacts form - and after I inspected the markup with devtools I saw the problem. Netlify adds a hidden input to forms to protect data from bots and spam. But it adds it with invalid markup:

<input type="hidden" name="form-name" value="contact">
   <input name="bot-field" data-v-75a227fb>
</input>

Do you see the input nested into another input? In HTML inputs cannot have children, so the above markup is invalid and Nuxt just couldn’t operate properly on it.

Nuxt usually generates files for you and checks validation before that, and your build simply won’t pass if some markup is invalid. In my case, Netlify adds broken input after all the build and generate has passed - and Nuxt isn’t used to invalid markup, and throws the error.

After some experiments, I could figure out that it adds invalid inputs only to a non-empty form, which gave me an idea.

The plan:

1. Create a hidden empty Netlify form

2. Create a real from to collect the data

3. Submit real form using ajax

Here is the minimal setup:

<template>
<div>
  <form
    ref="hiddenForm"
    name="contact"
    method="post"
    netlify
    netlify-honeypot="bot-field"
  >
    <p class="hidden">
      <input name="bot-field" />
    </p>
  </form>
  <form @submit="submit">
    <input
      v-model="email"
      type="email"
      name="email"
      placeholder="Email"
      required
    />
    <button>Send</button>
  </form>
</div>
</template>

<script lang="ts">  
import { Component, Vue } from 'vue-property-decorator'
import axios, { AxiosRequestConfig } from 'axios'

@Component({})
export default class Contacts extends Vue {
    email = ''

    encode(data) {
        return Object.keys(data)
            .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`)
            .join('&')
    }

    netlifySubmit() {
        const hiddenForm = this.$refs.hiddenForm as HTMLFormElement
        const axiosConfig = {
            header: { 'Content-Type': 'application/x-www-form-urlencoded' }
        }

        const form = {
            'form-name': 'contact',
            email: this.email
        }

        return axios
            .post(
                hiddenForm.action,
                this.encode({
                    ...form
                }),
                axiosConfig as AxiosRequestConfig
            )
            .then(() => {
                // show success message here
            })
    }

    submit(e) {
        e.preventDefault()
        this.netlifySubmit()
    }
}
</script>

Hope it helps to save some of your time and energy!

(づ。◕‿‿◕。)づ

I’m INTERESTED

PLEASE SELECT

Please sum up two numbers: zero and five

Also recommended