Angular 14 Authentication Form Tutorial: FormBuilder
Example with Node Backend
Throughout this step by step tutorial, we’ll be learning about how to create an Angular 14 web application with an authentication form for signing up users using Angular 14FormBuilder
, FormGroup
, and Validators
APIs.
> ✋✋ Join our Facebook group 👈 to discuss anything related to Angular 14 development.
Prerequisites
This tutorial has a few prerequisites such as:
- Node.js and npm installed on your development machine,
- Angular CLI 14 installed, if not use the
npm install -g @angular/cli
command to install it. For Angular 14 CLI, you need to usenpm install -g @angular/cli
at this time, since it’s still in beta version.
Now, let’s start with the first step of our Angular 14 tutorial.
Step 1 — Initializing your Angular 14 Project
Let’s get started by initializing an Angular 14 example project.
Head over to a new command-line interface and run:
$ ng new angular14authexample
Angular CLI will prompt if Would you like to add Angular routing? Say y and Which stylesheet format would you like to use? Pick CSS.
Step 2 — Generating the Authentication and Admin Components
In the second step of our Angular 14 tutorial and example, we’ll proceed to generate the authentication and admin components.
Go back to your command-line interface and navigate to the root folder of your project:
$ cd angular14authexample
Next, run the ng generate
command to generate the Angular 14 components:
$ ng generate component auth
$ ng generate component admin
We created two AuthComponent
and AdminComponent
components.
The auth component will be used to add a reactive form for getting the user’s email and password.
The admin component will be used as an example page that will be secured against access from non-authenticated users. Users will need to log in before they can access the admin page.
Next, include these two components in the routing module. Head to the src/app/app-routing.module.ts
file and update it as follows:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';import { AuthComponent } from './auth/auth.component';
import { AdminComponent } from './admin/admin.component';const routes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'login'},
{ path: 'auth', component: AuthComponent },
{ path: 'admin', component: AdminComponent }
];@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
We have created three routes:
- For the auth component,
- For the admin component.
- One for redirecting the empty path to the auth path.
Let’s remove this default HTML code. Open the src/app/app.component.html
file and remove everything but leave <router-outlet>
:
<router-outlet></router-outlet>
In the next step of our tutorial, we’ll see how to create a user model.
Step 3 — Creating a User Model
Let’s now create a User
interface. Head back to your command-line interface and run:
$ ng generate interface user
Go to the src/app/user.ts
file and update it as follows:
export interface User {
email: string;
password: string;
}
This will ensure each user will have an email and password.
Step 4 —Creating an Angular 14 Authentication Service
Next, let’s create an Angular 14 service that exports the methods required for authenticating users. In your command-line interface, run:
$ ng generate service auth
Go to the src/app/auth.service.ts
file and update it accordingly:
import { Injectable } from '@angular/core';
import { User } from './user';@Injectable({
providedIn: 'root'
})
export class AuthService { constructor() { } public signIn(userData: User){
localStorage.setItem('ACCESS_TOKEN', "access_token");
} public isLoggedIn(){
return localStorage.getItem('ACCESS_TOKEN') !== null; } public logout(){
localStorage.removeItem('ACCESS_TOKEN');
}
}
The signIn method is not fully implemented. For a real-world implementation, check out Using Angular HttpClient with Node & Express.js — Example POST Requests.
Step 5 — Creating an Angular 14 Router Guard
After creating the components, service, and model for implementing authentication.
Let’s generate a router guard that will be used for guarding the admin
component from the access of the non-authenticated users.
Go back to your command-line interface and run:
$ ng generate guard auth
Go to the src/app/auth.guard.ts
file and update it as follows:
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service';@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService){}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean { return this.authService.isLoggedIn(); }
}
We start by importing AuthService
and injecting it via the authentication guard’s constructor.
Next, in the canActivate()
method, we implement the logic that will grant or deny access to the user by calling the isLoggedIn()
method for checking if the user is logged in before activating the route.
This is simply how this works. The canActivate()
method returns true if the isLoggedIn()
methods return true i.e if the user is logged in. In this case, the route which has this guard applied can be accessed by the user.
Next, you only need to apply this guard to the route you want to guard.
Go to the src/app/app-routing.module.ts
file and update it accordingly:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';import { LoginComponent } from './login/login.component';
import { AdminComponent } from './admin/admin.component';
import { AuthGuard } from './auth.guard';
const routes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'login'},
{ path: 'login', component: LoginComponent },
{ path: 'admin', component: AdminComponent, canActivate: [AuthGuard] }
];@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
We use the canActivate
array of the admin
route to apply AuthGuard
to the route which protects it from users that are not logged in.
✋✋ Also, Check out ✋✋
Set title in Angular 14 with TitleStrategy
How to change page title with routing in Angular application?
Angular 14 Components and NgModules
How to Build Auto-Saving Forms in Angular 14
Angular ngFor with Index and trackBy Example
Add Bootstrap to Angular 14 App
Angular 14 — Upload Files with FormData and HttpClient
A Practical Tutorial to Angular 14: Environment and Project Setup
👇👇 Continue below 👇👇
Step 6 — Creating the Authentication Form
Before using reactive forms in Angular 14 we need to import FormsModule
and ReactiveFormsModule
in the application module.
Open the src/app/app.module.ts
file and update it accordingly:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule} from '@angular/forms';import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AuthComponent } from './auth/auth.component';
import { AdminComponent } from './admin/admin.component';@NgModule({
declarations: [
AppComponent,
AuthComponent,
AdminComponent
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
We can now use reactive forms in our application!
Open the src/app/login.component.ts
file and import:
FormBuilder
,FormGroup
,Validators
symbols that are used to create Angular reactive forms,Router
for routing,AuthService
and theUser
model.
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { User } from '../user';
import { AuthService } from '../auth.service';
Next, inject the FormBuilder
, Router
and AuthService
via the service constructor:
export class AuthComponent implements OnInit { constructor(private authService: AuthService, private router: Router, private formBuilder: FormBuilder ) { } ngOnInit() {
}
}
Next, add these service variables:
authForm: FormGroup;
isSubmitted = false;
Next, in the ngOnInit()
life-cycle event, create the form:
ngOnInit() {
this.authForm = this.formBuilder.group({
email: ['', Validators.required],
password: ['', Validators.required]
});
}
Next, add a get property to make easy to access the form controls on the HTML form:
get formControls() { return this.authForm.controls; }
Finally, add the signIn()
method:
signIn(){
this.isSubmitted = true;
if(this.authForm.invalid){
return;
}
this.authService.signIn(this.authForm.value);
this.router.navigateByUrl('/admin');
}
Next, we need to create the HTML form. Open the src/app/login.component.html
file and update it as follows:
<h1 style="text-align:center">
Angular 14 Auth Example
</h1>
<div class="login">
<h2 class="login-header">Log in</h2>
<form [formGroup]="authForm" class="login-container" (ngSubmit)="signIn()"> <p [ngClass]="{ 'has-error': isSubmitted && formControls.email.errors }">
<input type="email" placeholder="Email" formControlName="email">
</p> <div *ngIf="isSubmitted && formControls.email.errors" class="help-block">
<div *ngIf="formControls.email.errors.required">Email is required</div>
</div> <p [ngClass]="{ 'has-error': isSubmitted && formControls.password.errors }">
<input type="password" placeholder="Password" formControlName="password">
</p> <div *ngIf="isSubmitted && formControls.password.errors" class="help-block">
<div *ngIf="formControls.password.errors.required">Password is required</div>
</div> <p>
<input type="submit" value="Log in">
</p>
</form>
</div>
For styling the form we’ll be using this codepen example.
Open the src/styles.css
and add:
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700);
body {
background: #456;
font-family: 'Open Sans', sans-serif;
}
Next, open the src/app/login.component.css
file and these styles:
/* 'Open Sans' font from Google Fonts */
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,700);
.login {
width: 400px;
margin: 16px auto;
font-size: 16px;
}
.login-header,
.login p {
margin-top: 0;
margin-bottom: 0;
}
.login-triangle {
width: 0;
margin-right: auto;
margin-left: auto;
border: 12px solid transparent;
border-bottom-color: rgb(15, 66, 107);
}
.login-header {
background: rgb(12, 77, 129);
padding: 20px;
font-size: 1.4em;
font-weight: normal;
text-align: center;
text-transform: uppercase;
color: #fff;
}
.login-container {
background: #ebebeb;
padding: 12px;
}
.login p {
padding: 12px;
}
.login input {
box-sizing: border-box;
display: block;
width: 100%;
border-width: 1px;
border-style: solid;
padding: 16px;
outline: 0;
font-family: inherit;
font-size: 0.95em;
}
.login input[type="email"],
.login input[type="password"] {
background: #fff;
border-color: #bbb;
color: #555;
}
.login input[type="email"]:focus,
.login input[type="password"]:focus {
border-color: #888;
}
.login input[type="submit"] {
background: rgb(1, 29, 51);
border-color: transparent;
color: #fff;
cursor: pointer;
}
.login input[type="submit"]:hover {
background: #17c;
}
.login input[type="submit"]:focus {
border-color: #05a;
}
Also, add this CSS styles for error class:
.has-error input[type="email"],
.has-error input[type="password"] {
border-color: rgb(216, 12, 12);
color: rgb(230, 14, 14);
}
Step 7 — Creating the Admin Component
Go to the src/app/admin.component.ts
file and update it as follows:
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from '../auth.service';@Component({
selector: 'app-admin',
templateUrl: './admin.component.html',
styleUrls: ['./admin.component.css']
})
export class AdminComponent implements OnInit { constructor(private authService: AuthService, private router: Router) { } ngOnInit() {
} logout(){
this.authService.logout();
this.router.navigateByUrl('/login');
}}
Next, open the src/app/admin.component.html
file and add:
<div style="text-align:center">
<h1>
Welcome Admin!
</h1>
<p>
<button (click)="logout()">
Logout
</button>
</p>
<img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
</div>
Finally, open the src/app/admin.component.css
file and add:
button{
background: rgb(1, 29, 51);
border-color: transparent;
color: #fff;
cursor: pointer;
}
This is the screenshot of our admin page:
You can log out from the admin page and you will be redirected to the authentication form.
Conclusion
In this Angular 14 tutorial, we have implemented an authentication form with validation using Angular 14 reactive forms.