I'm trying to use Nativescript code sharing between web and mobile with Angular and I installed latest stable version etc.. But a lot of npm modules like for example :"nativescript-localstorage" when I start using it it gives me: "Can't resolve 'tns-core-modules/file-system/file-system-access'" even after the module author tested it few hours after updating his module etc.. but for me it's not working
4 Answers
I had the same issue. So I have made a service which is a wrapper of native localStorage.
After that, I inject my wrapper in my web app module and in my mobile app module. But for the mobile app module, I inject nativescript-localstorage instead of my wrapper.
Like my wrapper have the same functions than the nativescript-localstorage class, Angular see only the fire and I can use my wrapper to deal with localStorage in mobile and web!
In reality, when it's in web context, Angular use the 'native' localStorage and when it's in a mobile context, Angular use the nativescript-localstorage lib.
Below my code.
My service wrapper:
import { Injectable } from "@angular/core";
@Injectable()
export class CustomStorageService {
setItem(key, value){
localStorage.setItem(key, value);
}
getItem(key){
return localStorage.getItem(key);
}
removeItem(key){
localStorage.removeItem(key);
}
clear(){
localStorage.clear();
}
}
In app.module.ts:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { CustomStorageService } from './commons/core/services/guard/custom-storage.service';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule
],
providers: [
CustomStorageService
],
bootstrap: [AppComponent]
})
export class AppModule { }
My app.module.tns.ts:
import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
import { NativeScriptModule } from 'nativescript-angular/nativescript.module';
import { NativeScriptHttpClientModule } from 'nativescript-angular/http-client';
import * as mobileStorage from 'nativescript-localstorage';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent,
],
imports: [
NativeScriptModule,
AppRoutingModule,
NativeScriptHttpClientModule,
NativeScriptFormsModule
],
providers: [
{
provide: CustomStorageService,
useValue: mobileStorage
}
],
bootstrap: [AppComponent],
schemas: [NO_ERRORS_SCHEMA]
})
export class AppModule { }
An example of wrapper's usage:
import { Injectable } from '@angular/core';
import { CustomStorageService } from './custom-storage.service';
@Injectable()
export class TokenService {
constructor(private storage: CustomStorageService){
}
getToken(): String {
return this.storage.getItem('token');
}
saveToken(token: String) {
this.storage.setItem('token',token);
}
destroyToken() {
this.storage.removeItem('token');
}
destroyAll(){
this.storage.removeItem('token');
this.storage.removeItem('user_id');
this.storage.removeItem('user_name');
this.storage.removeItem('full_name');
}
destroyUser() {
this.storage.removeItem( 'currentUser' );
}
cleanLocalStorage() {
this.storage.clear();
}
}
Hope it will help.
You can use nativescript-localstorage but keep in mind that this is a plugin that will work in a mobile environment (iOS and Android) and not in a web project. That said when you create your code shared project (between Web and NativeScript) you should create logic that uses the plugin only in the NativeScript files.
For example, create files that name ends with .tns and ad the logic for the plugin there.
home.component.ts // web file
home.component.tns.ts // NativeScript file
Full POC app demonstrating the above and using nativescript-localstorage can be found here. To test the project on a mobile device/emulator run
tns run android --bundle
to test with Angular Web project run
ng serve -o
You can use the dependency injection feature to provide the appropriate storage implementation in your modules:
app.module.ts (web):
providers: [
{
provide: Storage,
useValue: localStorage
}
]
app.module.tns.ts (mobile):
import * as mobileLocalStorage from 'nativescript-localstorage';
providers: [
{
provide: Storage,
useValue: mobileLocalStorage
}
]
With the above setup, you can inject the Storage in your services and components and Angular will provide the correct implementation at run-time.
export class AuthenticationService {
constructor(private localStorage: Storage) {
}
}