Ninja Space Content Tech Blog

Week Six of Learning Angular

Posted by Ninja Space Content on Wednesday, April 21, 2021 Under: angular
This week, I am going to be taking notes on reactive forms in Angular. Reactive forms is where you explicitly create the forms that's more complex, like implementing async validation.

Reactive Forms
In order to use formControlName, you'll need to import ReactiveFormsModule to the array on imports in the app.module.ts file. Then, it'll automatically add it as an import to the top of that page like so: 
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
 
There was a bug that I kept getting following the first part of Programming with Mosh's Angular tutorial. The error was Object is possibly 'null'. This is related to my newer Angular version. I had to make sure the object is truthy in my && conditionals. Here's my html code that I have to fix it:  

<form [formGroup]="form">
    <div class="form-group">
        <label for="username">Username</label>
        <input 
            formControlName="username"
            id="username" 
            type="text" 
            class="form-control">
            <div *ngIf="username && username.touched && username.invalid" class="alert alert-danger">Username is required.</div>
    </div>
    <div class="form-group">
        <label for="password">Password</label>
        <input 
            formControlName="password"
            id="password" 
            type="text" 
            class="form-control">
    </div>
    <button class="btn btn-primary" type="submit">Sign Up</button>
</form>
 
When creating reactive forms, remember to import Validators at the top of the ts file. Here is my code as an example in the ts file:

import { Component } from '@angular/core';
import {FormGroup, FormControl, Validators} from '@angular/forms';

@Component({
  selector: 'signup-form',
  templateUrl: './signup-form.component.html',
  styleUrls: ['./signup-form.component.css']
})
export class SignupFormComponent {
  form = new FormGroup({
    username: new FormControl('', Validators.required),
    password: new FormControl('', Validators.required)
  });

  get username() {
    return this.form.get('username');
  }
}

Display Loader Image or Message
You can use the pending property to display a message, which is so nifty! Here is an example: 

<div *ngIf="username && username.pending">Checking...</div>
 
Simple Error for a Form Because of Angular Version
There as another thing that was different with my latest Angular version and it had to do with AbstractControl. In Programming with Mosh' Angular Tutorial, he used:

removeTopic(topic: FormControll) { let index = this.topics.controls.indexOf(topic);this.topics.removeAt(index); }
 
and this kept throwing a error in my terminal with the following:  Argument of type 'AbstractControl' is not assignable to parameter of type 'FormControl'.

It was I had to change FormControl to AbstractControl and then that fixed it. So my reactive form has the following code in the ts file:
import { Component} from '@angular/core';
import { FormArray, FormControl, FormGroup, AbstractControl} from '@angular/forms';

@Component({
 selector: 'new-course-form',
 templateUrl: './new-course-form.component.html',
 styleUrls: ['./new-course-form.component.css']
})

export class NewCourseFormComponent {
 form = new FormGroup({
 topics: new FormArray([])
 });

 addTopic(topic: HTMLInputElement) {
 this.topics.push(new FormControl(topic.value));
 topic.value='';
 }

 removeTopic(topic: AbstractControl) {
 let index = this.topics.controls.indexOf(topic);
 this.topics.removeAt(index);
 }

 get topics() {
 return this.form.get('topics') as FormArray;
 }
}
And my html file has the following code:

<form>
    <label>Form Array</label>
    <input 
    type="text" class="form-control"
    (keyup.enter)="addTopic(topic)" #topic
    >
    <ul class="list-group">
        <li 
        *ngFor="let topic of topics.controls"
        (click)="removeTopic(topic)"
        class="list-group item">
        {{topic.value}}
      
        </li>
    </ul>
</form>

FormBuilder
These section seemed a bit redundant to me so I didn't code it along with Mosh for this part. It was only a few minutes long. I will revisit FormBuilder some time again in the future.

Multi-Cursor Editing
The cool thing that learned during this particular session is multi-cursor editing. So I can just select the particular word or variable that I'd like to change, press Command and D as many times needed, edit my word and then it'll change those for me.

Abstract Control Error with Possible Null Value
While I was trying to get my validators working in a ts file, I kept getting an error about the object possibly being null when I used Mosh's code. 

In his code, he had:  

static passwordsShouldMatch(control: AbstractControl) {
        let newPassword = control.get('newPassword');
        let confirmPassword = control.get('confirmPassword');

        if (newPassword.value !== confirmPassword.value)
            return { passwordsShouldMatch: true};
            
            return null;
    }

I had to add two more conditionals to get rid of the compile error. Here's my code to fix the error:

static passwordsShouldMatch(control: AbstractControl) {
        let newPassword = control.get('newPassword');
        let confirmPassword = control.get('confirmPassword');

        if (newPassword && confirmPassword && newPassword.value !== confirmPassword.value)
            return { passwordsShouldMatch: true};
            
            return null;
    }

Then, when I was working with its html,  I also encountered object not null possibility error so here were my adjustments. I had to add a couple more truthy conditionals:  

<div class="form-group">
        <label for=''>Confirm Password</label>
        <input formControlName="confirmPassword" type="password" class="form-control">
        <div 
            *ngIf="confirmPassword && confirmPassword.touched && confirmPassword.invalid"
            class="alert alert-danger">
        <div *ngIf="confirmPassword.errors && confirmPassword.errors.required">New confirm password is required.</div>
        </div>
        <div *ngIf="confirmPassword && confirmPassword.valid && form.invalid && form.errors && form.errors.passwordsShouldMatch" class="alert alert-danger">Passwords do not match.</div>
    </div>

Whew, this form section was really hard for me to plow through but I did it! I'm about 29% of the way through the Programming with Mosh tutorial for Angular and it took me 6 weeks guys. I had another project I'm working on and also accepted a writing pitch so that took some of my hours away from this tutorial. However, I am eager to finish it. Read my list of week-to-week Angular notes.

In : angular 


Tags: learning angular  reactive forms  examples  typescript 

About Ninja Space Content


Ninja Space Content I have been building simple websites on my own since 2008 and currently run several websites at the moment, including this one. I used to be an account manager for an affiliate/e-commerce company, helping affiliates grow their sales so I have some knowledge on the business side and client side of affiliate marketing. During the Covid-19 pandemic, I completed a JavaScript coding bootcamp and graduated in Dec 2020. I've been working as a contractor for a few software companies ever since.
Note: links to resources and promoting special deals may allow me to earn a small commission from each sale.