Our First Reactive Form – My First App with Angular 8

Let’s make a series of entries in which we’ll create an application with Angular 8 and Firebase. The application will be a ToDo App, that is, a task manager app. It will use the Cloud Firestore database, and Firebase Authentication for the login system.

Related entries

  1. Introduction 
  2. Configuring Firebase and Bootstrap in Angular. Understanding Cloud Firestore
  3. Creating our first component – Click event  
  4. Our first reactive form <– You are here
  5. Saving and reading data in Cloud Firestore – ngIf and ngFor
  6. Introduction to Routing
  7. Login system with Angular and Firebase
  8. Releasing our Angular App in Azure with VS Code

As I publish the articles, I will be placing the links here above☝.

Our First Reactive Form

Now what we must do is work on the component that will be the form of the tasks, from this component we can create and edit tasks. For now we will concentrate on being able to create tasks.

Let’s go to the file todo-form.component.html that we created in the previous entry and we’ll paste the following code:

 

 

 

 

 

 


<div class="modal-header">
 <h4 class="modal-title">Create Todo</h4>
 <button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
   <span aria-hidden="true">&times;</span>
 </button>
</div>
<div class="modal-body">
 <form [formGroup]="todoForm" (ngSubmit)="saveTodo()">
   <div class="form-group">
     <label for="title">Title*</label>
     <input type="text" id="title" placeholder="Title" class="form-control" formControlName="title" />
     <span style="color:Red;" *ngIf="todoForm.controls['title'].touched && todoForm.controls['title'].errors?.required">Title
       is required.</span>
   </div>
   <div class="form-group">
     <label for="description">Description*</label>
     <textarea  id="description" placeholder="Description" class="form-control" formControlName="description"></textarea>
     <span style="color:rgb(238, 235, 235);" *ngIf="todoForm.controls['description'].touched && todoForm.controls['description'].errors?.required">Description
       is required.</span>
   </div>
   <div class="form-check">
     <input class="form-check-input" type="checkbox" value="" id="done" formControlName="done">
     <label class="form-check-label" for="done">
       Done
     </label>
   </div>
 </form>
</div>
<div class="modal-footer">
 <button type="button" class="btn btn-outline-dark" (click)="activeModal.close('Close click')">Close</button>
 <button class="btn btn-primary" (click)="saveTodo()" [disabled]="todoForm.invalid">Save</button>
</div>

The central theme of this component is, of course, the form:

 

 

 

 


<form [formGroup]="todoForm" (ngSubmit)="saveTodo()">

We see that we have the [formGroup] property on this form. The formGroup allows us to define an object which will have the configuration of our form. It is through the todoForm property that we can also access the values that the user enters in the form.

Inside of the form we have 3 controls:

 

 


<div class="form-group">
<label for="title">Title*</label>
<input type="text" id="title" placeholder="Title" class="form-control" formControlName="title" />
<span style="color:Red;" *ngIf="todoForm.controls['title'].touched && todoForm.controls['title'].errors?.required">Title
is required.</span>
</div>
<div class="form-group">
<label for="description">Description*</label>
<textarea id="description" placeholder="Description" class="form-control" formControlName="description"></textarea>
<span style="color:rgb(238, 235, 235);" *ngIf="todoForm.controls['description'].touched && todoForm.controls['description'].errors?.required">Description
is required.</span>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="done" formControlName="done">
<label class="form-check-label" for="done">
Done
</label>
</div>

These controls are: Title, Description, and a checkbox that allows to indicate if the task is done or not. Something very important that we see in the 3 controls is the formControlName attribute. This attribute helps us to be able to access the value of the controls from the class of the component, that is, we use formControlName to identify an HTML control from JavaScript in a reactive form.

Note also that we have some span whose text will be red, in these we place an error message if a validation rule of the form is not being fulfilled.

And, in the end, we have two buttons, a close button, to close the modal, and a save button, to save the form information:

 

 

 


<button type="button" class="btn btn-outline-dark" (click)="activeModal.close('Close click')">Close</button>
<button class="btn btn-primary" (click)="saveTodo()" [disabled]="todoForm.invalid">Save</button>

Here we see that we have an attribute between brackets: disabled. Basically, what the brackes do is that it allows us to dynamically alter the value of an attribute of an HTML tag. The disabled attribute disables the Save button, in our case, we are saying that when the form is invalid, then the save button will be disabled. A form is said to be invalid when at leat one of its validation rules is not respected. When the form is valid, then the button will be enabled to be clicked. This [disabled] is known as property binding.

Let’s talk now about the form itself. As I was saying, this is a reactive form. The idea of ​​a reactive form is that we will have a model in the class of the component which will represent the information filled in the form. Thus, when we fill in the fields of the form, in the end, we will have an object in our class which will have all the information that we fill in the form. In addition, other configurations, such as validation rules, will be configured in the component class, and not in the form.

Now, let’s go to the class of this component and let’s put the following code in it:

 

 

 

 

 


import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'app-todo-form',
templateUrl: './todo-form.component.html',
styleUrls: ['./todo-form.component.css']
})
export class TodoFormComponent implements OnInit {
todoForm: FormGroup;
constructor(private formBuilder: FormBuilder,
  public activeModal: NgbActiveModal) { }
ngOnInit() {
    this.todoForm = this.formBuilder.group({
      title: ['', Validators.required],
      description: ['', Validators.required],
      done: false
});
}
}

The first thing we need is a class called FormBuilder to help us build the formGroup. For that we injected it via the constructor. Notice also that we have a property of the FormGroup type called todoForm. This is the class through which we control the configuration of the reactive form.

Then, we work with the ngOnInit method. We use the ngOnInit method when we want to perform certain initialization tasks of our component. In this case, we initialize the fields of the form (title, description and done):

 


this.todoForm = this.formBuilder.group({
  title: ['', Validators.required],
  description: ['', Validators.required],
  done: false
});

This code uses the FormBuilder to create a FormGroup. The FormGroup will have an object of 3 properties, these properties match the controls that we place in the form in the template of the component, that is, with the formControlName of each control. The textbox with formControlName “title” will be synchronized with the title property of the formGroup, so that in this property the value that the user places in the corresponding textbox can be found using JavaScript.

Look at the title property, we are assigning an array with a first value that is an empty string, this will be the initial value of the control in the form, and the second value of the array is a synchronous validation rule, which says that the field it is required:

title: [, Validators.required],

If we do not want to place validation rules on a field of a form, we can simply not pass  any validator, as we do with the done property, which is a Boolean, and by default, its value is false:

done: false

We can try the form, if we go back to Google Chrome, we can click Add All, and we will get a form with three controls: title, description, and whether the task has been done or not. Notice that the Save button is disabled. If I click on the textbox of the title, and then click on another place, I am shown an error message indicating that said field is required. Finally, if we fill in all the required fields, the Save button is enabled.

We already have the UI of the form and its basic configuration. Now, we really want to save the data that is entered in the form in our Cloud Firestore database. We’ll see that in the next post.

Regards!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s