In angular application development, we call localstorage in typescript code
It retrieves data from local storage through key. However, on the server, this code crashes with an error message:
ReferenceError: localStorage is undefined
When running the angular application on the server, the standard browser API is missing from the global space
For example, in server-side rendering mode, developers cannot directly access global document objects as in client-side rendering environment. To obtain a reference to a document, you must use the document token and the angular dependency injection mechanism di
Do not use browser APIs through global space, but replace or disable browser implementations through Di so that they can be used safely on the server
Refer to the following code:
import {Component, Inject, NgModule} from '@angular/core';
import {LOCAL_STORAGE} from '@ng-web-apis/common';
@Component({...})
export class SomeComponent {
constructor(@Inject(LOCAL_STORAGE) localStorage: Storage) {
localStorage.getItem('key');
}
}
The above example uses local from the @ ng web APIs / common package_ Storage token. But when we run this code on the server, we get an error. Just add universal from the @ ng web APIs / universal package from the providers of appservermodule_ LOCAL_ Store and pass the token local_ Storage, so you can get the localstorage implementation of the server.
import { NgModule } from '@angular/core';
import {
ServerModule,
} from '@angular/platform-server';
import { AppModule } from './app.module';
import { AppComponent } from './app.component';
import { UNIVERSAL_LOCAL_STORAGE } from '@ng-web-apis/universal';
@NgModule({
imports: [
AppModule,
ServerModule,
],
providers: [UNIVERSAL_LOCAL_STORAGE],
bootstrap: [AppComponent],
})
export class AppServerModule {}
Look at the following conditional rendering code:
<>
@Component({
selector: 'ram-root',
template: '<some-сomp *ngIf="isServer"></some-сomp>',
styleUrls: ['./app.component.less'],
})
export class AppComponent {
isServer = isPlatformServer(this.platformId);
constructor(@Inject(PLATFORM_ID) private platformId: Object){}
}
This angular component needs to obtain platform_ ID, target platform, and understand the public properties of the class. This attribute will be used with the ngif directive in the template.
We have a more elegant implementation:
First create an injection token:
<>
export const IS_SERVER_PLATFORM = new InjectionToken<boolean>('Is server?', {
factory() {
return isPlatformServer(inject(PLATFORM_ID));
},
});
Then create a custom Directive:
@Directive({
selector: '[ifIsServer]',
})
export class IfIsServerDirective {
constructor(
@Inject(IS_SERVER_PLATFORM) isServer: boolean,
templateRef: TemplateRef<any>,
viewContainer: ViewContainerRef
) {
if (isServer) {
viewContainer.createEmbeddedView(templateRef);
}
}
}
Then directly use the structure directive on the component:
<>
@Component({
selector: 'ram-root',
template: '<some-сomp *ifIsServer"></some-сomp>',
styleUrls: ['./app.component.less'],
})
export class AppComponent {}
Additional properties have been removed from the component. The component template is now simpler, focusing only on the business logic it wants to implement.