How to get Netlify Forms working with Nuxt 3
Contents
I love working with Nuxt. I love the simplicity it creates when building websites and apps using VueJS. Similarly, Netlify makes hosting easy and cost-effective. Netlify includes many built-in features that can supercharge your Nuxt app. One of them is Netlify Forms.
Netlify Forms makes form submissions easy. Easy, but not necessarily stress-free. In this article, I want to show you three examples of integrating Netlify Forms with Nuxt. There are also a few gotchas that stumped me in some previous projects that I want to tell you about.
I will include a link to this tutorial's GitHub repository. There, you can download all the code for reference.
The easy way to integrate Netlify Forms with Nuxt
In this example, we have a simple form. The form is for users to vote on their favourite JavaScript framework. The form consists of a text input for the user's name, a dropdown for their role and radio options for them to cast their vote.
At present, this form will not integrate with Netlify Forms. We must add a few extra bits to the code for Netlify to recognise the form. As the Netlify Forms documentation states, we must add the 'data-netlify' attribute to the form element. So we can recognise our form in the Netlify platform, we must name it. To do this, we add the 'name' attribute to the form element along with our chosen name. In this case, I called my form 'framework-votes'.
The final step to initialise our form is to add a hidden input element in our form. This element means the form's name is included in the POST request. This way, Netlify knows where to store the submission.
<form action="/simple-netlify-form" method="post" enctype="application/x-www-form-urlencoded" data-netlify="true" name="framework-votes">
<input type="hidden" name="form-name" value="framework-votes" />
<!-- Form fields here -->
</form>
If we deploy our app now, Netlify can't detect it. This is because Netlify scans the HTML of our app before the JavaScript runs. Our form is created by JavaScript, so Netlify can't see it is there. To fix this, we must prerender our form. We configure prerendering in the 'nuxt.config.js' file under the 'nitro' object. Inside that object, we create a nested object named: 'prerender', and then inside that object, add an array named 'routes'. The routes array tells Nuxt which routes to prerender. In my case, the form is on the root page. So, I add '/' to my array. You will add the route for the page your form is on. For reference, here is my Nuxt configuration.
export default defineNuxtConfig({
pages: true,
nitro: {
prerender: {
routes: [ '/', '/simple-netlify-form', '/ajax-netlify-form', '/conditional-rendering-netlify-form' ]
}
},
...
});
Now, we can upload our form to Netlify. For the platform to auto-detect your form, navigate to the 'Forms' link in the sidebar in Netlify. You should be presented with the option to 'Enable form detection'. If you click that button, your form should be detected. If not, redeploying your site should prompt Netlify forms to find your form.
How to use AJAX and Netlify Forms in a Nuxt app
Using AJAX with Nuxt is relatively simple. Netlify does a great job of explaining it in the documentation. In their example, they create a form data object and pass the form element as a parameter. In Nuxt, we can add a ref to the form element and pass that to the form data constructor.
Occasionally, we may need to manipulate some of the form data before sending our POST request. In this case, we can maintain our form's state using a ref or reactive object. Using JSON makes it easier to manipulate our data. Before we send our request, we pass our data through a function to encode it in cURL format. The function will use an algorithm like the one denoted below.
const encode = (data) => Object.keys(data).map(key => encodeURIComponent(key) + "=" + encodeURIComponent(data[key])).join("&");
Using AJAX to send our POST request allows us to add different response messages to the screen without reloading the page. See my example below of adding success and error messages based on the status of the POST request.
<template>
<form data-netlify="true" name="toilet-votes" @submit.prevent="handleSubmit">
<!-- Form fields here -->
<p class="response-message" v-if="formResponse">{{ formResponse }}</p>
</form>
</template>
<script setup>
// Form Submission
const formResponse = ref(null);
const handleSubmit = (e) => {
const { position, percent } = formEntries;
const formData = {
position,
percent,
'form-name': 'toilet-votes'
}
fetch('/conditional-rendering-netlify-form', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: encode(formData)
})
.then(() => formResponse.value = 'Thank you for sharing.')
.catch((e) => formResponse.value = e.message);
}
</script>
How to implement conditional rendering for Netlify Forms in Nuxt
Finally, we have a slightly more complex implementation of Netlify Forms. For any seasoned VueJS Developer, this shouldn't be a challenge. Still, implementing this on my site caused a few issues. These took an afternoon to fix. That afternoon of banging my head against a brick wall prompted me to write this article. Hopefully, I can save someone else the same trouble.
In this example, we conditionally render some fields. Watch the video below to see what I mean.
The trick to achieving this is to use v-show instead of v-if. When I first built a Netlify Form on Nuxt this way, I used v-if. That was a mistake. When using v-if, the conditional element is only added to the DOM when its condition passes. Otherwise, it does not exist. For Netlify to recognise our form, we must prerender it. If the conditional element is not in the DOM when it prerenders, Netlify does not know it exists and won't extract its data from our POST request. To avoid this issue, we use v-show. With v-show, the element is hidden from the user but still exists in the DOM. We must also remember to implement ARIA-hidden on the inactive element. Otherwise, the form will not work correctly for accessibility users.
Answering my own question
There is plenty of documentation around Netlify Forms. Not much of it is relevant to VueJS and Nuxt. Certainly not the latest versions, anyway. When troubleshooting my forms, I have had to shoehorn in various fixes from React and native HTML solutions. I felt it was time to collate my findings in a blog post. That way, anyone facing similar issues doesn't need to do the same digging I did. Moving forward, I intend to write more articles like this. Creating a knowledge base around my stack and front-end development experience may prove helpful to others using similar technology. If you have any further questions on this topic, don't hesitate to contact me by email.