Reputation: 440
I am using @angular v4.0.3 and webpack 2.2.0.
It was working fine using Auler post but as I included localStorage it stopped working. Is there any way to make it work or any module for localStorage in angular universal
Upvotes: 5
Views: 5360
Reputation: 3745
Angular Universal Set Localstorage using simple Platform Browser or Platform Server Here is the component file
components.ts
import { PLATFORM_ID} from '@angular/core';
import { Inject } from '@angular/core';
import { Router } from '@angular/router';
import { isPlatformBrowser } from '@angular/common';
@Component({
selector: 'app-navigation',
templateUrl: './navigation.component.html',
styleUrls: ['./navigation.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class NavigationComponent implements OnInit {
locale_Menu: any = [];
defaultURL: any;
defaultURLpath: any;
private isBrowser: boolean = false;
constructor(
@Inject(DOCUMENT) private dom: Document,
private router: Router,
@Inject(PLATFORM_ID) private platformId: Object
) {
this.isBrowser = isPlatformBrowser(platformId);
}
ngOnInit(): void {
this.generalAppSettings.subscribe((location: any) => {
this.locale_Menu = location.localeMenu.continents;
});
this.defaultURL = new URL(this.dom.URL);
this.defaultURLpath = this.defaultURL?.pathname.split('/');
if (this.defaultURLpath.length == 2) {
if (this.isBrowser) {
var retrievedLocale = localStorage?.getItem('preferredLocale');
if (retrievedLocale) {
const navigateURL = this.defaultURL?.pathname.replace(
this.defaultURLpath[1],
retrievedLocale
);
this.router.navigate([navigateURL]);
} else {
this.router.navigate([this.defaultURL]);
}
}
}
}
changeLocale(category: any): void {
const locale = this.coreService.locales.find((l) => l.code === category);
if (locale) {
let _URL = this.defaultURL.pathname.replace(
this.defaultURL.pathname.split('/')[1],
locale.code
);
if (this.defaultURLpath.length == 2) {
window.localStorage.setItem('preferredLocale', locale.code);
}
this.router.navigate([_URL]).then(() => {
window.location.reload();
});
}
}
}
Upvotes: 0
Reputation: 2315
This happens because using Angular Universal for Server Side Rendering, the Angular app runs in both the Nodejs server and the client browser. At this point, the server app does not have a reference to the localStorage object, because it is only available on the client-side.
There's an article I wrote about this with the solution implemented: How to use localStorage on Angular 9 Universal (SSR)
Upvotes: 2
Reputation: 222498
A good way is to make localStorage
an injectable and provide different implementations for it.
An abstract class that reflects Storage
API can be used as a token:
export abstract class LocalStorage {
readonly length: number;
abstract clear(): void;
abstract getItem(key: string): string | null;
abstract key(index: number): string | null;
abstract removeItem(key: string): void;
abstract setItem(key: string, data: string): void;
[key: string]: any;
[index: number]: string;
}
Then for browser app module it is
export function localStorageFactory() {
return localStorage;
}
...
{ provide: LocalStorage, useFactory: localStorageFactory }
And for server app module localStorage
can be replaced with some implementation, like node-storage-shim
for in-memory storage:
{ provide: LocalStorage, useClass: StorageShim }
Using DI instead of global persistent storage also makes testing easier.
Upvotes: 7