Save User Data in Local Storage in Angular 16 Firebase
Today we are going to create a simple app in which we are going to save user data in local storage using Angular and Firebase real-time database.
I will be showing you how you can maintain the user state even after you refresh the page in the Angular and Firebase.
I am going to use a simple logic when a user logs in the app we will save the user data in local storage.
When a user logs out from the Angular application we remove the user data from local storage and set it to null.
Advantages of saving user’s data as an object in localStorage
- Local Storage provides full control to users to access their data.
- A user’s data can be retrieved quickly and easily.
- It works even after you lose the internet connection, you can still access the data.
Let’s start coding our small app.
1. Prerequisite
– Setup Node JS development environment
Before we move further I assume you’ve already set up Node JS development environment in your system.
Please follow this article on Set up Node JS Development Environment
– Install Angular CLI
Install Angular CLI, Ignore if already installed.
npm install -g @angular/cli
– Angular Project Set up
Set up the latest Angular project.
ng new angularfiebase-authentication
Once the project is installed, get into the project folder.
cd angularfirebase-authentication
Congrats! You are in your project directory.
In order to remove strict type warnings or error make sure to set “strict”: false under compilerOptions property in tsconfig.json file.
Install Bootstrap 5 for demo purpose from NPM community.
npm install bootstrap
Go to angular.json
file and replace the given below code with “styles”: [ ] array.
"styles": [
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"src/styles.scss"
]
Type given command to generate components:
ng g c components/sign-in
ng g c components/dashboard
2. AngularFire2 Library Integration
I assume you already know how to create a basic Firebase account and setup a project in it, if not then follow this article How to setup a basic Firebase account and set up a Firebase Project?
How to include Firebase AngularFire2 library in your Angular app?
Add AngularFire2 library in your Angular app using Angular CLI.
npm install @angular/fire firebase@9.16.0 --legacy-peer-deps
First, create src/environments/ folder and environment.ts file, then add firebase configurations in environments/environment.ts file.
export const environment = {
production: false,
firebase: {
apiKey: "xxxxxxxx-xxxxxxxx",
authDomain: "xxxxxxxxxxxxxxxxxxxxxxxx",
projectId: "xxxxxxxx",
storageBucket: "xxxxxxxx",
messagingSenderId: "xxxxxx",
appId: "xxxxx",
}
};
Once the AngularFire2 library included in the app then go to src/app/app.module.ts
file and add the given below code.
// Firebase services + enviorment module
import { AngularFireModule } from "@angular/fire";
import { AngularFireAuthModule } from "@angular/fire/auth";
import { environment } from '../environments/environment';
@NgModule({
declarations: [...],
imports: [
AngularFireModule.initializeApp(environment.firebase),
AngularFireAuthModule
],
providers: [...],
bootstrap: [...]
})
4. Implement Router Service
Now, head over to the app/app-routing.module.ts
file, here you have to update the code into the file.
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { SignInComponent } from './components/sign-in/sign-in.component';
import { DashboardComponent } from './components/dashboard/dashboard.component';
const routes: Routes = [
{ path: '', redirectTo: '/sign-in', pathMatch: 'full' },
{ path: 'sign-in', component: SignInComponent },
{ path: 'dashboard', component: DashboardComponent },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
5. Create Auth Service
I am going to create AuthenticationServicefile, this file will hold following logics.
– Create authentication.service.ts
file
This file holds the core logic of our authentication service. I’ll be covering up following methods in it.
- Sign in with Google
- Saving user data as an object in localStorage at login
- Removing user data object from localStorage at log out
import { Injectable, NgZone } from '@angular/core';
import * as auth from 'firebase/auth';
import { AngularFireAuth } from '@angular/fire/compat/auth';
import { Router } from '@angular/router';
@Injectable({
providedIn: 'root',
})
export class AuthenticationService {
userData: any;
constructor(
public afAuth: AngularFireAuth,
public router: Router,
public ngZone: NgZone
) {
this.afAuth.authState.subscribe((user) => {
if (user) {
this.userData = user;
localStorage.setItem('user', JSON.stringify(this.userData));
JSON.parse(localStorage.getItem('user'));
} else {
localStorage.setItem('user', null);
JSON.parse(localStorage.getItem('user'));
}
});
}
SignIn(email, password) {
return this.afAuth
.signInWithEmailAndPassword(email, password)
.then((result) => {
this.ngZone.run(() => {
this.router.navigate(['dashboard']);
});
})
.catch((error) => {
window.alert(error.message);
});
}
GoogleAuth() {
return this.AuthLogin(new auth.GoogleAuthProvider());
}
AuthLogin(provider) {
return this.afAuth
.signInWithPopup(provider)
.then((result) => {
this.ngZone.run(() => {
this.router.navigate(['dashboard']);
});
})
.catch((error) => {
window.alert(error);
});
}
SignOut() {
return this.afAuth.signOut().then(() => {
localStorage.removeItem('user');
this.router.navigate(['sign-in']);
});
}
}
After that, go to src/app.module.ts
file and import authentication service and pass the AuthenticationService class into providers: [AuthenticationService]
array. By doing this our authentication service will be available throughout the application.
// Auth service
import { AuthenticationService} from "./shared/services/authentication.service";
@NgModule({
declarations: [...],
imports: [...],
providers: [AuthenticationService],
bootstrap: [...]
})
6. Setting up Sign in with Google in Angular Template
In order to consume AuthenticationService class from authentication.service.ts
file we need to import AuthenticationService
service into components/sign-in/sign-in.component.ts
file and then inject AuthenticationServiceclass into the constructor so that these services will be available throughout the same template.
Go to sign-in.component.ts
file and paste the following code.
import { Component, OnInit } from '@angular/core';
import { AuthenticationService} from '../../authentication.service';
@Component({
selector: 'app-sign-in',
templateUrl: './sign-in.component.html',
styleUrls: ['./sign-in.component.scss'],
})
export class SignInComponent implements OnInit {
constructor(public authenticationService: AuthenticationService) {}
ngOnInit() {}
}
Go to sign-in/sign-in.component.html
file and include the given below code.
<div class="displayTable">
<div class="displayTableCell">
<div class="authBlock">
<h3>Sign In</h3>
<!-- Calling GoogleAuth Api from AuthenticationService-->
<div class="formGroup">
<button
type="button"
class="btn googleBtn"
(click)="authenticationService.GoogleAuth()"
>
<i class="fab fa-google-plus-g"></i>
Log in with Google
</button>
</div>
</div>
</div>
</div>
7. Check user data in Browser Console When not Logged In
When you are not lgged in, you see user === null
in browser’s application console.
8. Check user data in Browser Console After Logged In
When you are lgged in, you see user data in browser’s application console.
9. Reteriving User Data and Showing up in Dashboard Component
Go to dashboard.component.ts
add the following code.
import { Component, OnInit } from '@angular/core';
import { AuthenticationService} from '../../authentication.service';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss'],
})
export class DashboardComponent implements OnInit {
constructor(public authenticationService: AuthenticationService) {}
ngOnInit() {}
}
Go to dashboard.component.html
file, and add the data into HTML tags.
<!-- Top navigation -->
<nav class="navbar navbar-dark fixed-top bg-dark flex-md-nowrap p-0 shadow">
<span class="dasboard-text">Dashboard</span>
</nav>
<!-- Sidebar navigation -->
<div class="container-fluid">
<div class="row">
<nav class="col-md-2 d-md-block bg-light sidebar">
<div class="sidebar-sticky">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link active">
<i class="fas fa-user"></i>User Profile
</a>
</li>
<!-- Calling SignOut() Api from AuthenticationService-->
<li class="nav-item">
<a class="nav-link" (click)="authenticationService.SignOut()">
<i class="fas fa-sign-out-alt"></i>Log out
</a>
</li>
</ul>
</div>
</nav>
<!-- Main content -->
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-4">
<div class="inner-adjust">
<div class="pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">User Profile</h1>
</div>
<!-- Show user data when logged in -->
<div class="row" *ngIf="authenticationService.userData as user">
<div class="col-md-12">
<div class="media">
<img
class="align-self-start mr-5 img-thumbnail rounded-circle"
src="{{
user.photoURL ? user.photoURL : '/assets/dummy-user.png'
}}"
alt="{{ user.displayName }}"
/>
<div class="media-body">
<h1>
Hello:
<strong>{{
user.displayName ? user.displayName : "Super Admin"
}}</strong>
</h1>
<p>
User ID: <strong>{{ user.uid }}</strong>
</p>
<p>
Email: <strong>{{ user.email }}</strong>
</p>
<p>
Email Verified: <strong>{{ user.emailVerified }}</strong>
</p>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
Here is the final code example of app.module.ts file.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AuthenticationService } from './authentication.service';
import { AngularFireModule } from '@angular/fire/compat';
import { AngularFireAuthModule } from '@angular/fire/compat/auth';
import { AngularFireStorageModule } from '@angular/fire/compat/storage';
import { AngularFirestoreModule } from '@angular/fire/compat/firestore';
import { AngularFireDatabaseModule } from '@angular/fire/compat/database';
import { environment } from '../environments/environment';
import { SignInComponent } from './components/sign-in/sign-in.component';
import { DashboardComponent } from './components/dashboard/dashboard.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFireAuthModule,
AngularFirestoreModule,
AngularFireStorageModule,
AngularFireDatabaseModule,
],
providers: [AuthenticationService],
bootstrap: [AppComponent]
})
export class AppModule { }
Please also have a look on app-routing.module.ts file and update the code in your file as given below:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { SignInComponent } from './components/sign-in/sign-in.component';
import { DashboardComponent } from './components/dashboard/dashboard.component';
const routes: Routes = [
{ path: '', redirectTo: '/sign-in', pathMatch: 'full' },
{ path: 'sign-in', component: SignInComponent },
{ path: 'dashboard', component: DashboardComponent },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
Next, also add the router outlet directive in app.component.html file.
<router-outlet></router-outlet>
Run the following command to start your project.
ng serve --open
Conclusion
Thanks a lot for taking the time to read this tutorial, I hope this tutorial has been helpful to you. If you think this tutorial has helped you then must share this tutorial with others.
Download complete code of this tutorial from GitHub.