To Do App using Angular Forms - part 1
Tags: angular, beginners, webdev, tutorial
Published: 2022-02-15 06:32:25

Before we dive into creating an angular form, we need to clarify that there are two approaches to handle forms in Angular.

- **Template-driven approach**. Your first set up the form in the template in your HTML code. Angular will then infer the structure of the form from there. The template-driven approach is the easiest way to get started with forms in Angular.
- **Reactive approach**. You start from the class with your typescript code. The reactive approach is programmatical, and it potentially offers more advanced customization capabilities. Take a glance at What is RxJS.

In this post, we will use the template-driven approach. 
If you are not familiar with event binding you may want to look at this [simple app](https://www.vitainbeta.org/2022/02/06/simple-angular-to-do-app/) that explains it.

## Template-driven Angular Form 
### Creating the form
We start by using the traditional `<form>` HTML element. 

```
// app.component.html

<form>
  <label for="userInput">Add Task</label>
  <input
    placeholder="Write a task"
    name="userInput"
    required
  />
  <label for="date">By when</label>
  <input type="date" name="date" />
  <button type="submit">Add</button>
</form>
```
As you can see, there is no action or method attribute. Unlike traditional HTML forms, we don't want to submit a form to some server. Angular should handle it. 

At the moment, the application looks like this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bedmc39lw7r17ozkjwmn.png)

As usual, I will omit CSS but I will link the entire code later.

Make sure that you are importing FormsModule in app.module.ts! FormsModule is required to handle the form. Your app.module.ts should be similar to this:

```
//  app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';

@NgModule({
  imports:      [ BrowserModule, FormsModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }
```

Thanks to FormsModule, Angular will automatically create a JavaScript representation of the form as soon as a `form` tag is detected in the template. 

You can think of the JavaScript representation of the form as a regular JavaScript object that contains key-value pairs corresponding to the elements in the form.

### Adding controls
Now, we need to tell Angular what kind of controls we have in the form. Angular doesn't detect the control elements automatically because not all elements need to be controls.

To tell Angular which element is a control we need to specify two things

1. **ngModel**. We add ngModel to the element we want to use as a control. As you might know, ngModel is commonly used in [two-way data binding](https://www.vitainbeta.org/2021/09/15/passing-angular-data-to-the-parent-component/#two-way-binding). 
2. **Name of the control**. We need to specify the name of the control. So, we use the traditional HTML attribute name.

```
// app.component.html

<form>
  <label for="userInput">Add Task</label>
  <input 
    placeholder="Write a task" 
    ngModel 
    name="userInput" 
    required 
  />
  <label for="date">By when</label>
  <input  
    type="date"  
    name="date" 
    ngModel 
  />
  <button type="submit">Add</button>
</form>
```
With this, I registered two elements in the JavaScript representation of the form.

I used the HTML attribute `name` to assign the name of the control, therefore this is also completed.

### Submit Angular Forms

Angular Forms capitalizes on the default behavior of an HTML form. When a user clicks on the submit button, the button submits the form, triggers a request and submit a javascript submit event.

Angular uses the `ngSubmit` directive in the form tag. `ngSubmit` is an event listener that will fire whenever the form is submitted.
To verify that this is working fine, we add the event listener to the form tag. 


```
// app.component.html

<form (ngSubmit)="onSubmit()">
  ...
</form>
```

The `ngSubmit` event listener triggers the `onSubmit()` method that we have to create in our component. For the moment, the `onSubmit()` method logs a string into the console.

```
app.component.ts

export class AppComponent {
  ...

  onSubmit() {
    console.log('Submitted');
  }
}

```

When we click on the add button, we see the text Submitted in the console. Ok, that is already something! Angular submits the forms correctly or at least ngSubmit fires the event adeguately.

## Pass Angular Forms data

We need to add some code to expose the data in the Angular Form. In other words, we want to get access to the automatically generated javascript object in the Angular form.

To get access to the object, we set a local reference equal to ngForm in the form tag `#myForm="ngForm"`. This tells Angular to give us access to the form, read javascript object, created automatically.

```
// app.component.html

<form (ngSubmit)="onSubmit(myForm)" #myForm="ngForm">
  ...
</form>
```

Notice that I passed the local reference `myForm` to the `onSubmit` method.

We need to update the `onSubmit` method in app.component.ts to receive the form object of type NgForm.

```
app.component.ts

import { NgForm } from '@angular/forms';
...

export class AppComponent {
  ...

  onSubmit(form: NgForm) {
    console.log('Submitted', form);
  }
}

```

At this point, when you submit the form you can see the NgForm object in the console. Feel free to play around and peek inside the object. Curiosity is the best way to learn.

In the picture below, you can see a screenshot of part of the form object. 
You can already see the controls and value keys
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w3ex2u289cg1fbvge9x0.png)
 
Inside the value property you will find the values associated with the controls that we defined above: userInput and date.

If you log `form.form.value` you will get an object:

```
{
    "userInput": "some user input abc",
    "date": "2022-02-09"
}
```

Notice that you might want to use HTML5 validation. Since Angular disables it by default, it is necessary to add ngNativeValidate  to the form in the template.