Netlify Forms is a form handling feature that receives submissions from HTML forms automatically. In this article, we’ll cover how to use it with Angular reactive forms and how to deploy the finished app on Netlify’s hosting platform, Netlify Edge.

Creating the frontend, backend, and deployment workflow of an app takes a lot of work. In instances where your app collects only a limited amount of data submissions from its users, building a whole backend may not seem worth the time and effort. An alternative to developing a complete backend is using Netlify Forms. In this tutorial, I’ll explain how you could use an Angular reactive form with Netlify Forms. Since Netlify Forms only work when deployed on Netlify, I’ll also illustrate how to deploy your app on Netlify Edge.

The Toolkit

An Angular reactive form is a form that has a structured data model created explicitly within a component class using the ReactiveFormsModule providers. A form model is created for each input element within the form view. This form model is an instance of the FormControl class and it keeps track of the value of the form element. The form model is immutable because whenever a change is made to the model the FormControl instance returns a new data model instead of updating the old model. Its immutability makes change detection more efficient and allows data alteration with observable operators. Since form input elements are directly connected to their form models, updates between them are synchronous and do not rely on UI rendering.

Netlify is a platform that allows you to build, deploy, and host sites built with various technologies. Sites built with Angular can be hosted on Netlify. Netlify additionally provides a host of tools that simplify, automate, and augment builds and deployments of these sites. We’re going to use two of its products in this tutorial: Netlify Edge and Netlify Forms.

As described earlier, Netlify Forms is a form handling feature that receives submissions from HTML forms automatically. It does not require any submission processing configuration, like creating APIs, scripts, etc. This feature only works with forms in sites deployed on Netlify. It is enabled by default, further reducing the configuration needed to set up the form submissions. Submission handling is set up during deployment where a site’s HTML files are parsed by Netlify’s build bots.

Netlify Edge is a global application delivery network on which sites and applications are published. It provides features like A/B testing, rollbacks, staging, and phased rollouts. All deployments on Netlify Edge are atomic, meaning a site is only live when all files have been uploaded/updated and changes to the site are ready. Once a site is deployed, it is assigned a subdomain on netlify.app when deployed to production. Netlify Edge also supports preview and branch deployments (staging, development, etc.).

Netlify Forms submission-handling works because build bots parse HTML forms on a site during deployment. Client-side Javascript rendered forms like those in compiled Angular sites won’t be found by these bots. So the normal set up for Netlify Forms won’t work with Angular Forms.

However, there is a work-around to this. To get it to receive submissions, a hidden plain HTML form is added to the index.html file. This form works with the build bots. When submitting the Angular Form, a post request is made to this hidden form which is then captured by Netlify Forms.

In this article, we will create a reactive form. We’ll also develop a service to make a post request to the hidden HTML form. Lastly, we will deploy the app to Netlify Edge.

Example

To illustrate how to build the app, we will take an example of a feedback form common on many websites. We will use this form to collect comments/complaints, questions, and suggestions from users of the site along with their name and email. We shall also use it to collect their rating of the site.

Requirements

To follow along with this tutorial, you will need a Netlify account and the Angular CLI installed. If you do not have the CLI, you can install it using npm.

npm install -g @angular/cli

If you’ve not signed up for a Netlify account yet, you can create one here. Netlify offers sign-up through Github, Gitlab, Bitbucket, or Email. Depending on what deployment method you choose to go with, they may be other requirements. They will be stated under each deployment method.

Setting Up The App

To start, we will create the app and call it feedback. When creating it, add routing to it when asked in the prompts.

ng new feedback

Next, we’ll generate three components: a feedback form, a successful submission message page, and a 404 page. Netlify Forms allow you to navigate to a page upon successful form entry submission. That’s what we’ll use the SuccessComponent for.

ng g c feedback
ng g c success
ng g c page-not-found

After generating the components, we’ll add the routes to each page in the AppRoutingModule within the app-routing.module.ts file.

const routes: Routes = [
  { path:'', component: FeedbackComponent },
  { path: 'success', component: SuccessComponent },
  { path: '**', component: PageNotFoundComponent }
];

We’ll use the FormBuilder service to create our reactive form. This is because it is more convenient and less repetitive than using basic form controls. To have access to it, we’ll need to register the ReactiveFormsModule in the app.module.ts file.

Since we will be making a post request to the hidden HTML form, we also have to register the HttpClientModule.

import { ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  imports: [
    // other imports
    ReactiveFormsModule,
    HttpClientModule
  ]
})
export class AppModule { }

Proceed to change the contents of app.component.html to just have the router outlet.

<router-outlet></router-outlet>

The different pages will share some styling. So add the styling below to styles.css.

html, body {
    height: 100%;
    width: 100%;
    display: flex;
    align-items: flex-start;
    justify-content: center;
}

h1 {
    margin: 0;
    text-align: center;
}

h1, p, label {
    font-family: Arial, Helvetica, sans-serif;
}

p {
    max-width: 25rem;
}

#container {
    border: none;
    padding: .4rem;
    border-radius: 0;
    flex-direction: column;
    display: flex;
}

hr {
    width: 80%;
}

button {
    color: white;
    background-color: black;
    font-size: large;
    padding: .5rem;
    border-radius: .5rem;
    margin-top: 1rem;
}

@media screen and (min-height: 700px) {
    html, body {
        align-items: center;
        justify-content: center;
    }
}

@media screen and (min-width: 480px) {
    #container {
        border: .1rem solid lightgray;
        padding: 2rem;
        border-radius: .5rem;
    }

    html, body {
        align-items: center;
        justify-content: center;
    }
}

Create The Reactive Form

In our FeedbackComponent class, we will begin by importing the FormBuilder service which we’ll use to create the form. We’ll also import the Validators class for form input validation.

import { FormBuilder, Validators } from '@angular/forms';

We will then inject the FormBuilder service by adding it to the FeedbackComponent constructor.

constructor(private fb: FormBuilder) { }

Next, we’ll define the form model using the group method of the injected FormBuilder service. We’ll also add an errorMsg property to hold any errors we may encounter when submitting the form input. Also included is a closeError method that will close the error alert that displays on the form.

Each control in the form model will be verified using validators from the Validators class. If any of the inputs fail validation, the form will be invalid and submission will be disabled. You can choose to add multiple validators to a form control like in the case of the email control.

export class FeedbackComponent {
  feedbackForm = this.fb.group({
    firstName: ['', Validators.required],
    lastName: ['', Validators.required],
    email: ['', [Validators.email, Validators.required]],
    type: ['', Validators.required],
    description: ['', Validators.required],
    rating: [0, Validators.min(1)]
  });

  errorMsg = '';

  closeError() {
    this.errorMsg = '';
  }

  // ...
}

In the component’s template (feedback.component.html), we shall add this.

<div id="container">
  <div class="error" [class.hidden]="errorMsg.length == 0">
    <p>{{errorMsg}}</p>
     ✖︎
  </div>
  <h1>Feedback Form</h1>
  <hr>
  <p>We’d like your feedback to improve our website.</p>
  <form [formGroup]="feedbackForm" name="feedbackForm" (ngSubmit)="onSubmit()">
    <div id="options">
      <p class="radioOption">
        <input formControlName="type" type="radio" id="suggestion" name="type" value="suggestion">
        <label for="suggestion">Suggestion</label><br>
      </p>
      <p class="radioOption">
        <input formControlName="type" type="radio" id="comment" name="type" value="comment">
        <label for="comment">Comment</label><br>
      </p>
      <p class="radioOption">
        <input formControlName="type" type="radio" id="question" name="type" value="question">
        <label for="question">Question</label><br>
      </p>
    </div>
    <div class="inputContainer">
      <label>Description:</label>
      <textarea rows="6" formControlName="description"></textarea>
    </div>
    <div class="inputContainer">
      <div id="ratingLabel">
        <label>How would you rate our site?</label>
        <label id="ratingValue">{{feedbackForm.value?.rating}}</label>
      </div>
      <input formControlName="rating" type="range" name="rating" max="5">
    </div>
    <div class="inputContainer">
      <label>Name:</label>
      <div class="nameInput">
        <input formControlName="firstName" type="text" name="firstName" placeholder="First">
        <input formControlName="lastName" type="text" name="lastName" placeholder="Last">
      </div>
    </div>
    <div class="inputContainer">
      <label>Email:</label>
      <input formControlName="email" type="email" name="email">
    </div>
    <div class="inputContainer">
      <button type="submit" [disabled]="feedbackForm.invalid">Submit Feedback</button>
    </div>
  </form>
</div>

Note that the form element should have the [formGroup]="feedbackForm" attribute corresponding to the model we just created. Also, each of the input elements should have a formControlName="" attribute corresponding to its counterpart form control in the model.

#angular #netlify #javascript #programming #developer

Build And Deploy An Angular Form With Netlify Forms And Edge
1.80 GEEK