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 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:
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
- 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.
- 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
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.
Top comments (0)