I created one application in angular 12. There I used localstorage for storing different values. Then I applied Angular universal in that project. I got many errors related to window, localstorage, etc. So to resolve that I installed mock browser and added global variables in server.ts like follow:
const MockBrowser = require('mock-browser').mocks.MockBrowser;
const mock = new MockBrowser();
global['window'] = mock.getWindow();
global['document'] = mock.getDocument();
global['localStorage'] = mock.getLocalStorage();
global['navigator'] = mock.getNavigator();
global.DOMParser = window.DOMParser;
I have applied canActivate on routes and I have applied logic which checks currentUser from localStorage. If that exists then return true else false, like below
app.routing.module.ts
{ path: "user-timeline", component: TimelineComponent,canActivate : [AuthGuard] },
auth.guard.ts
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): boolean | UrlTree {
if (!this.authService.isLoggedIn()) {
this.openConfirmationDialog(route);
return false;
}
return true;
}
auth.service.ts
import {LocalstorageService} from "src/app/services/localstorage.service";
export class AuthService {
constructor(
private _localStorage: LocalstorageService,
) {}
isLoggedIn() {
console.log('isLoggedIn',this._localStorage.getItem("currentUser"));
if (this._localStorage.getItem("currentUser")) {
console.log('isLoggedIn if');
return true;
}
return false;
}
}
ARTICLE by @Santi Barbat
I have applied localStorage as per this article. Like mentioned in that article added code in app.component.ts and created service LocalstorageService with same code. Injected that service and replaced my previous localStorage with this service variable like above used in auth.service.ts
It works fine until I manually click on browser reload. When I click on browser reload button, localStorage data becomes undefined.
Like mentioned in that article, used isPlatformBrowser also. Also tried by installing node-storage-shim for server side rendering and used in local storage service like below
LocalStorage service
import { Injectable } from "@angular/core";
import { AppComponent } from "../app.component";
class LocalStorage implements Storage {
[name: string]: any;
readonly length: number;
clear(): void {}
getItem(key: string): string | null {
return undefined;
}
key(index: number): string | null {
return undefined;
}
removeItem(key: string): void {}
setItem(key: string, value: string): void {}
}
@Injectable({
providedIn: "root",
})
export class LocalstorageService implements Storage {
private storage: Storage;
constructor() {
this.storage = new LocalStorage();
AppComponent.isBrowser.subscribe((isBrowser) => {
if (isBrowser) {
this.storage = localStorage;
} else {
const StorageShim = require("node-storage-shim");
this.storage = new StorageShim();
}
});
}
[name: string]: any;
length: number;
clear(): void {
this.storage.clear();
}
getItem(key: string): string | null {
return this.storage.getItem(key);
}
key(index: number): string | null {
return this.storage.key(index);
}
removeItem(key: string): void {
return this.storage.removeItem(key);
}
setItem(key: string, value: string): void {
return this.storage.setItem(key, value);
}
}
app.component.ts
import { Component, Inject, PLATFORM_ID } from "@angular/core";
import { TranslateService } from "@ngx-translate/core";
import { BehaviorSubject } from "rxjs";
import {isPlatformBrowser} from '@angular/common';
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent {
static isBrowser = new BehaviorSubject<boolean>(null);
constructor(public translate: TranslateService,
@Inject(PLATFORM_ID) private platformId: any) {
AppComponent.isBrowser.next(isPlatformBrowser(platformId));
}
}
In short, in server side rendering I am not able to retain or use localStorage data on browser relaod. Also I have observed that if I remove canActivate from routes then page reloads and shows data like previous (which is strange)
Is there any way by which I can get localStorage data on browser reload in angular server side rendering?
Or if anyone has any other suggestion/solution for this problem will be of great help.
Please help and guide. Thanks.
so you can define a method named like: "initLocalStorage()" where to put the logic for creating a localStorage.