Netlify Forms: Invalid HTML of the hidden input element

According to (docs/form-handling/#ajax-form-submissions) you add a hidden input element. A valid HTMLInputElement has no closing tag and is void, i.e. it’s never closed. However, for some reason inside my Netlify App using Netlify Forms when inserted the hidden HTMLInputElement looks like this:

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

I’ve marked the above code snippet as XHTML, because this ^ is not valid HTML:

In HTML, the <input> tag has no end tag.
In XHTML, the <input> tag must be properly closed, like this <input />.

It’s causing an unexplicable error in Nuxt (Vue):
DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method.

Because it’s invalid Chrome tries to guess what’s happening and does this:
59931569-8b2ac100-9445-11e9-8dc2-cccea5c35805

It nests a text node and another HTMLInputElement inside of an HTMLInputElement, but since an Input Element is void it cannot have anything inside it and Vue does not know what’s going on at this point!

It’s very frustrating, because everything works fine on my development machine and the reason something goes wrong is something I cannot control. It’s been a major source of frustration in my life for the last few hours :dagger:

Hey @jcubed,

Thanks for pinging us on this. I tried to replicate your issue and I think the issue as you pointed out may have to do with invalid HTML. This issue on the Nuxt repo explain this a little more in depth.

It’s hard to tell where exactly in your application this is happening, but if it helps, I’ve created an example Nuxt app that includes a Netlify form for reference. Let me know if you still run into issues!

  • Divya

Hi, just wanted to chime in and say that you’re correct that Netlify forms shouldn’t be closing that input. I got an issue filed on that so we can get it fixed. @divya can speak more to the vue side of this, but if you can provide more information, including a code example, I’d love to see what’s happening since I haven’t seen others experience similar errors with netlify forms and nuxt.js

Thanks for getting back to me @futuregerald and @divya!

This issue seems weird if it’s only happening to me. I’ve recently made my project repo public. I have tested Netlify Forms on a feature branch and just left it there hanging once I couldn’t get it to work.

Here’s the exact place the forms are used: https://github.com/JakubKoralewski/mireks/blob/67a96bf0146bc4f1720b283be58cd765a4c02acb/components/Contact/Contact.vue#L22

Here’s the fetch request @submit.prevent event handler of the form: https://github.com/JakubKoralewski/mireks/blob/form-test/components/Contact/Contact.ts#L51

I don’t know what else could cause it since it’s working fine on my computer when I run both npm run dev and npm run generate but the issue happens when I put the site on Netlify. But then again if it happens only to me… weird.

Now I noticed the only thing different in my code and divya’s is that I wrap my inputs in labels, i.e.:

<label for="name">
    Your name:
    <input name="name">
</label>

While divya does this:

<label for="name">Your name:</label>
<input name="name">

According to W3Schools it’s valid:

Tip: A label can be bound to an element either by using the "for" attribute, or by placing the element inside the <label> element.

I guess my fors in labels are unnecessary ¯\(ツ)/¯. This is the syntax in your docs also (/docs/form-handling/). Maybe this is the culprit and the reason why it would be rare?

Hmm, hard for me to say as a total Vue newbie, but since you have a working setup already handy, maybe you could try without just to see if that helps and let us know?

Sure thing, chief.

So I did and the issue is gone!
Here’s the newly generated HTML that doesn’t produce errors:

<form name='contact-form' data-netlify-recaptcha='true' data-v-03c002d6 method='post'><input type='hidden' name='form-name' value='contact-form' /><label for="name" data-v-03c002d6>
				Twoje imię:
			</label> <input name="name" data-v-03c002d6> <label for="e-mail" data-v-03c002d6>
				Twój e-mail:
			</label> <input name="e-mail" data-v-03c002d6> <label for="body" data-v-03c002d6>
				Twoja wiadomość:
			</label> <textarea name="body" data-v-03c002d6></textarea> <label for="nie-wpisuj-tego" data-v-03c002d6>
				Nie wpisuj tego:
			</label> <input name="nie-wpisuj-tego" data-v-03c002d6> <div data-v-03c002d6>

Here’s the one producing the problem:

<form name='contact-form' data-netlify-recaptcha='true' data-v-3a49ccba method='post'><input type='hidden' name='form-name' value='contact-form' /><label for="name" data-v-3a49ccba>
				Twoje imię:
				<input name="name" data-v-3a49ccba></label> <label for="e-mail" data-v-3a49ccba>
				Twój e-mail:
				<input name="e-mail" data-v-3a49ccba></label> <label for="body" data-v-3a49ccba>
				Twoja wiadomość:
				<textarea name="body" data-v-3a49ccba></textarea></label> <label for="nie-wpisuj-tego" data-v-3a49ccba>
				Nie wpisuj tego:
				<input name="nie-wpisuj-tego" data-v-3a49ccba></label> 

Here’s the comparison of how it gets interpreted in Chrome (I couldn’t get two images in here so I had to improvise):
image

There’s still the uncertainty of whether the “Twoje imię” string will be shown in the new one since that text is contained inside an input and that’s not allowed (after interpreting in Chrome/Vue), but it shows up. I got the HTML snippets from view-source, but the images are from Chrome DevTools, so I’m not sure if it’s Chrome that makes the resulting HTML different from the source or maybe Vue behind the scenes trying to make sense of it all.

Seems like closing the input combined with the labels somehow causes the problem. Well, at least I got it working! Thanks.

1 Like

What code did you used in order to produce the correct HTML?

I have the same issue.

IIRC, all I needed was to remove the inputs from the labels, and instead put them on the same level (even though it should work with the inputs being children of labels).

So you should have whats tagged as NEW in the image above instead of OLD.

Ok I got it sorted out. For me it fixed by just adding the form-name field manually like <input type="hidden" name="form-name" value="contact"> (where the value should match your <form name="contact">)

However, Netlify (@divya) should fix this problem with invalid hidden element in a feature release :wink:

1 Like

glad it’s working now, @Reinos!

This post helped me as well. I was using Nuxt.js with vue-bootstrap and I was receiving “Node.appendChild: Cannot add children to a Text” as an error message.

I simply added the hidden form-name value and its functioning properly now. Just adding on to this post for search food for anyone who runs into the same issue. :slight_smile:

2 Likes

Cheers for the suggestions.

This worked for me:

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

      <label for="name">

        Name

      </label>

      <input name="name" type="text">

      <label for="email">

        Your email

      </label>

      <input name="email" type="email">

      <label for="body">

        Message

      </label>

      <textarea name="message" type="textarea"></textarea>

      <button type="submit">Send</button>

    </form>
1 Like

Hi @dubdubdub is the top of the form in your example missing a <form name="contact"> ?

I’m a little lost at the solution. I am using ‘for=’ as mentioned.

<template>
  <form
    class="form-group mt-1"
    data-netlify="true"
    data-netlify-honeypot="bot-field"
    action="/success"
    :name="formName"
    @submit="checkForm(formData, $event)"
    @submit.prevent="handleSubmit(formData, formName, $event)"
  >
    <!-- Hidden form-name-->
    <input type="hidden" :name="formName" :value="formName">
    <div class="d-flex flex-column mb-1">
      <label class="font-weight-600 mb-0 text-subtitle" :for="name">
        {{ label }}
      </label>
    </div>
    <div class="d-flex form-control-btn align-items-stretch align-self-start flex-column flex-md-row">
      <input
        :id="name"
        ref="inputRef"
        v-model="value"
        class="form-control border-primary form-control"
        type="text"
        :name="name"
      >
      <b-button class="hero mt-1 mt-md-0" variant="primary" type="submit">
        {{ buttonCopy }}
      </b-button>
    </div>
  </form>
</template>

Oh it turns out it should be:

<input type="hidden" name="form-name" :value="formName">
1 Like

Hi, @tettoffensive. Thank you for sharing this solution!