Connecting Netlify Forms to Angular

Template-Driven or Reactive Forms

Kristiyan Doykov
JavaScript in Plain English

--

Netlify is a great deployment solution, especially for simple, to-the-point apps. It provides the Forms feature which does away with having to create a backend only for the sake of form handling and email sending.

Angular is one of the most popular frontend frameworks around and offers loads of great features. Among these are its two form types — reactive and template-driven.

The two don’t go together “out-of-the-box” so let’s make them work!

The problem

In short, Angular works with components which means that our form will be rendered by client-side JavaScript. Therefore, the Netlify bots cannot identify the form and its fields because they do not exist during deployment.

The solution

We need to create an “invisible” form in our index.html which will be discoverable by the bots and we will submit that instead. This will be achieved via a POST request to our index page.

Before we get to the nitty-gritty details of it all, if you’re like me you probably like to have a checklist ready for the next app you might do this for. Here’s mine for reference:

  • Write your invisible form in index.html (use the same “name” attribute as the one in your actual form)
  • Write a suitable interface for the data you require
  • Generate a NetlifyForms service with ng g s NetlifyForms
  • Add a _redirects glob to your src folder containing the redirect rule /* /index.html 200
  • Include the glob in your angular.json assets array by adding the following line:
{ "glob": "_redirects", "input": "src", "output": "/" }
  • Use the NetlifyForms service in your form-containing component to submit the form

Right, so that’s the quick overview which will hopefully save you time in the future and make sure you’re not missing any important little bits.

Now for the in-depth process.

Here is what my visible form looks like:

As you can see I am using a template-driven form but this approach will work with a reactive form as well. However, file uploads are not supported so keep that in mind.

First we need to create a clone of our form in index.html . Here’s what mine looks like:

It’s important that you give the name attribute the same value as your actual form and also add the netlify attribute to signal the bots that you wish to handle this form via Netlify and finally add the netlify-honeypot="bot-field" attribute in order to activate the provided spam-bot protection.

You can also add a reCAPTCHA to your form by specifying the data-netlify-recaptcha="true" attribute and adding a div to your form where you wish the challenge to be displayed. Here’s what a finished reCAPTCHA form should look like:

<form name="contact" method="POST" data-netlify-recaptcha="true" data-netlify="true">
<p>
<label>Email: <input type="text" name="name" /></label>
</p>
<p>
<label>Message: <textarea name="message"></textarea></label>
</p>
<div data-netlify-recaptcha="true"></div>
<p>
<button type="submit">Send</button>
</p>
</form>

Next up we need to create an interface that suits the type of data we are going to be sending. Mine will be named Feedback and will reside in a feedback.ts file in the same folder as the component where my form sits.

Here is what my finished Feedback interface file looks like:

We should now create our Angular service which will handle our submissions to the index page form.

Run ng g s NetlifyForms to create the service.

And here is what your netlify-forms.service.ts file should look like:

As you can see we have two private functions to handle logging of errors as well as the actual submission and a third one which is accessible to other components in order to transform the feedback. It is important that we include the Content-Type header in the POST request and set it to application/x-www-form-urlencoded in order to submit the form in the correct data type.

We can now use our new service in the component where we submit our form (typically via a request to our server for example). In order to indicate to my users that their enquiry has been submitted or has failed to send I show a pop-up beneath my form. That’s why I have the emailSent and emailFailed variables (they’re not required). Here’s what my contact.component.ts file looks like:

You’ll also notice that we subscribe to our submitFeedback() function so it’s good to unsubscribe in the ngOnDestroy lifecycle method in order to prevent possible data leaks.

So far so good but even if you tried submitting the form now it would not work. What we need to do is re-route every request to our index.html file so that Angular can process it.

We write a very simple rule which states /* /index.html 200 . The /* captures any route and redirects it to our index.html file and returns a status code of 200 instead of the usual 301 used for redirects.

The above rule goes into a file (with no extension needed as it is just a glob) called _redirects which will reside in our src folder. We also need to include it in our assets array in angular.json which is achieved with the following line:

"assets": ["src/favicon.ico", "src/assets",{ "glob": "_redirects", "input": "src", "output": "/" }]

If you’re running ng serve for development on localhost you might still receive a 404 status code. This is because the you’re running on the development server which is set-up to serve our static files as well as to respond to GET requests routed to the root(/). Therefore, when we’re making a POST request containing our form data we end up with a 404 Not Found error. Not to worry though as this will work on Netlify.

There, you’re all set and ready to deploy your beautiful app to Netlify and read all your form submissions directly from the Forms dashboard or even set up email notifications if you wish.

Conclusion

Thank you for reading this article all the way through, I hope this approach has managed to solve your problem. If you’re also interested in how deployment works on Netlify you should check out this article where both of these steps are covered in detail and where I myself found the original solution from.

--

--

Passionate full-stack web and mobile developer and overall programming enthusiast.