# Angular JS

## Prerequisites

Angular basics:

* ***Services***
* ***TemplateForms***

***

## Let's move to the code part:

* Let's assume that you already initialized your app and you have your component that has the form.

1. Create a service (***mail***)

```JS
ng generate service services/mail
```

* define a method called (***sendEmail()***) that will return a *Promise* and accept a parameter (***formData***) that has type of (***FormData***).
* in the method we are going to return the *Promise* of the built in function (***fetch()***), which is accepting 2 arguments:

1. API endpoint: `https://api.web3forms.com/submit`.
2. Object with 2 properties: `{ method: 'POST', body: formData }`

* our ***service mail*** method should look like:

```JS
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class MailService {
  constructor() {}

  sendEmail(formData: FormData): Promise<Response> {
    return fetch('https://api.web3forms.com/submit', {
      method: 'POST',
      body: formData,
    });
  }
}
```

* that's it for the ***mail service***.

***

* Now let's take a look at the HTML ***form***:

*We are you using TailwindCSS for styling*

```JS
<!-- Form -->
<div class="mt-8">
<form
  class="flex flex-col gap-3"
  #contactForm="ngForm"
  (ngSubmit)="submitEmail(contactForm)"
>
  <!-- Name field -->
  <div>
    <input
      name="name"
      [(ngModel)]="contactFormValues.name"
      #name="ngModel"
      type="text"
      placeholder="Full Name"
      class="w-full p-2 border border-gray-200 rounded-md"
      required
      minlength="2"
    />
    <!-- input error message -->
    <p
      class="ml-1 text-red-400 text-sm"
      *ngIf="name.errors && name.touched && name.dirty"
    >
      name is required
    </p>
  </div>
  <!-- email field -->
  <div>
    <input
      name="email"
      [(ngModel)]="contactFormValues.email"
      #email="ngModel"
      type="email"
      placeholder="Email"
      class="w-full p-2 border border-gray-200 rounded-md"
      required
      pattern="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"
    />
    <!-- input error message -->
    <p
      class="ml-1 text-red-400 text-sm"
      *ngIf="email.errors && email.touched && email.dirty"
    >
      invalid email
    </p>
  </div>
  <!-- body field -->
  <div>
    <textarea
      name="body"
      [(ngModel)]="contactFormValues.body"
      #body="ngModel"
      cols="30"
      rows="10"
      class="w-full p-2 border border-gray-200 rounded-md"
      placeholder="Message"
      required
      minlength="20"
    ></textarea>
    <!-- input error message -->
    <p
      class="ml-1 text-red-400 text-sm"
      *ngIf="body.errors && body.touched && body.dirty"
    >
      at least write some words (20 characters length)
    </p>
  </div>
  <!-- Alert -->
  <div
    [ngClass]="{
      hidden: !showAlert
    }"
  >
    <p [ngClass]="alertColor" class="font-semibold">
      {{ alertMessage }}
    </p>
  </div>
  <!-- submit button -->
  <button
    [disabled]="contactForm.invalid || onSubmit"
    class="p-2 rounded-md font-bold uppercase text-white bg-light-color hover:bg-primary-color transition disabled:opacity-50 disabled:bg-light-color"
  >
    <ng-container *ngIf="onSubmit === false; else submittingEmail">
      send
    </ng-container>
    <ng-template #submittingEmail>
      <div class="animate-spin">
        <fa-icon [icon]="iconLoad"></fa-icon>
      </div>
    </ng-template>
  </button>
</form>
```

* As you can see we are assigning the values of the inputs to an object in our component class (***contactFormValues***) with the help of ***template forms***, and we have a button being used to submit the form as well as we have (***ng-container***) and (***ng-template***) inside the button tag to display whether the text (***send***) or show a spinning animated (***icon***) that indicates the form is being submitted.
* Let's take a look at the component class properties and methods:

> - Class properties:

```JS
  constructor(
    private mailService: MailService
  ) {}

  private color: string = '';
  showAlert: boolean = false;
  alertMessage: string = '';
  onSubmit: boolean = false;
  iconLoad = faArrowRotateForward;
  contactFormValues = {
    name: '',
    email: '',
    body: '',
  };
```

> * Class methods:

```JS
get alertColor() {
  return `text-${this.color}-400`;
}

hideAlert() {
  setTimeout(() => {
    this.showAlert = false;
  }, 5000);
}

async submitEmail(contactForm: NgForm) {
  this.onSubmit = true;
  // -- set formData values
  let formData: FormData = new FormData();
  formData.append('name', this.contactFormValues.name);
  formData.append('email', this.contactFormValues.email);
  formData.append('body', this.contactFormValues.body);
  // -- email customization
  formData.append('access_key', environment.form_access_key);
  formData.append('subject', 'Email Support From Your Site');
  formData.append('from_name', 'Contact Notification');

  try {
    // -- send email
    const res = await this.mailService.sendEmail(formData);
    if (!res.ok) {
      throw new Error();
    }
    this.alertMessage = 'Email sent successfully!';
    this.color = 'green';
    contactForm.reset();
  } catch (err) {
    // handle error
    this.alertMessage = 'Something went wrong, try again later!';
    this.color = 'red';
  }
  // -- reset submit and hide alert
  this.onSubmit = false;
  this.showAlert = true;
  this.hideAlert();
}
```

## Class properties explanation:

* `showAlert: boolean = false;` To display alert message (success or fail).
* `alertMessage: string = '';` To hold the alert message.
* `onSubmit: boolean = false;` To set and track submit state.
* `iconLoad = faArrowRotateForward;` To define and rename the icon from (fontAwesome library).
* contactFormValues `contactFormValues = { name: '', email: '', body: '', };`

To hold the inputs' values with the help of the template forms of Angular.

## Class methods explanation:

* `hideAlert()` To hide the alert message after 5 seconds.
* `submitEmail(contactForm)` An async function that accepts an instance of the ***NgForm*** to handle the submit form and in this method let's explain 3 parts of it:

1. Create a formData instance and append values (contactFormValues) because it is the way that *Web3Forms* accepts the form.

* `formData.append('name', this.contactFormValues.name);` add input value (***name***) from template to formData, follow the same steps to add the other inputs' values (***email***, ***body***).
* grab your ***access key*** from email you received earlier and add it into the environment variables, in our case we called it (***form\_access\_key***) see example below:
* `formData.append('access_key', environment.form_access_key);`
* `formData.append('subject', 'Email Support From Your Site');` to set subject text.
* `formData.append('from_name', 'Contact Notification');` to set a name for the form.

You can read more about customizations here: [Web3Forms Customization](https://docs.web3forms.com/getting-started/customizations)

2. `try | catch` blocks, in the `try` block we are calling the `mailService.sendEmail()` method to submit the form and in case the form was successfully submitted we show a success message and reset the values to `null` by the help of the instance `NgForm` that has `reset()` method, in our case it is `contactForm.reset()`, and in case there is an error we added a ***guard clause*** and inside its block we throw an error to force the code to jump to the `catch` block and show an error message.
3. and at the end of the method we reset `onSubmit` property to `false`, `showAlert` to `true` and call the `hideAlert()` method.

***

> ***Congratulations! You are all set up and ready to go.***

***

*This article is written by* [*CoderNadir*](https://dev.to/codernadir)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.web3forms.com/how-to-guides/js-frameworks/angular-js.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
